#1
  1. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Sep 2008
    Posts
    10
    Rep Power
    0

    Removal of list object and inserting it into variable works not as expected


    Hello,

    I wrote a module to create sorted double chained list - list can be traversed ascending and descending.
    This works fine.

    The module´s methods (among others) are:

    a) getBase("name"): loops throu the sorted list until it finds a list object with matching $self->{base} and returns that object.
    b) removeObject(): removes an object from list, updates it und returns that object.
    c) baseName(): returns $self->{base} of an list object.
    d) first() and $last(): look up first/last object in sorted list and return that object.
    e) previous() and next: return previous/next object in sorted list

    Just to remove a list object from $list works fine - $list still can be traversed ascending and descending.
    What I dont understand is: when the return value of removeObject is stored to $otherList the object in the list should have been updated and any reference to other list objects should have been undef-ed by method removeObject.
    But this is not the case like the output below proofs.

    I have no idea what`s going wrong.
    Thanks in advance for any hint

    Peter




    ### output of myProg.pl:

    $list->getBase("c"): doubleChained=HASH(0x6fb0c8)
    otherList: doubleChained=HASH(0x6fb0c8)

    LIST: list

    BASE: a
    BASE: b
    BASE: d
    BASE: e
    BASE: f
    ################################################################################
    LIST: otherList

    BASE: a
    BASE: b
    BASE: d
    BASE: e
    BASE: f




    ### myProg.pl

    PHP Code:
    BEGIN{unshift(@INC,"/root/bin/myModules/questinable");}

    use 
    strict;
    use 
    doubleChained;

    my $list=doubleChained->new(base => qw(a));

    $list->add(base => qw(b));
    $list->add(base => qw(b));
    $list->add(base => qw(c));
    $list->add(base => qw(d));
    $list->add(base => qw(e));
    $list->add(base => qw(f));

    print 
    "\$list->getBase(\"c\"): ",$list->getBase("c"),"\n";
    my $otherList=$list->getBase("c")->removeObject();
    print 
    "otherList: ",$otherList,"\n\n";

    my $loop=$list->first();

    print 
    "LIST: list\n\n";

    do {
            print 
    "BASE: ",$loop->baseName(),"\n";
    } while(
    defined($loop=$loop->next()));

    print 
    "################################################################################\n";

    $loop=$otherList->first();

    print 
    "LIST: otherList\n\n";

    do {
            print 
    "BASE: ",$loop->baseName(),"\n";
    } while(
    defined($loop=$loop->next())); 



    ### doubleChained.pm

    PHP Code:
    sub getBase {
            
    my $self=shift(@_);
            
    my $base=shift(@_);
            
    my $objRef=$first;

            do {
                    return(
    $objRef) if($base eq $objRef->{base});
            } while(
    defined($objRef=$objRef->{next}));

            return(
    undef);
    }

    sub removeObject {
            
    my $self=shift(@_);

            
    $first=$self->{next} if($first == $self);
            
    $last=$self->{previous} if($last == $self);
            
    $self->{previous}->{next}=$self->{next} if(defined($self->{previous}));
            
    $self->{next}->{previous}=$self->{previous} if(defined($self->{next}));
            
    $self->{previous}=undef;
            
    $self->{next}=undef;
            return(
    $self);
    }

    sub previous {
            
    my $self=shift(@_);
            return(
    $self->{previous});
    }

    sub next {
            
    my $self=shift(@_);
            return(
    $self->{next});
    }

    sub first {
            
    my $self=shift(@_);
            return(
    $first);
    }

    sub last {
            
    my $self=shift(@_);
            return(
    $last);
    }

    sub baseName {
            
    my $self=shift(@_);
            return(
    $self->{base});

  2. #2
  3. No Profile Picture
    Contributing User
    Devshed Intermediate (1500 - 1999 posts)

    Join Date
    Apr 2009
    Posts
    1,930
    Rep Power
    1225
    Your posted module code is incomplete which prevents us from doing and testing.

    Code:
    BEGIN{unshift(@INC,"/root/bin/myModules/questinable");}
    Is better written as:
    Code:
    use lib "/root/bin/myModules/questinable";
    What version of perl are you using?

    Code:
    print "\$list->getBase(\"c\"): ",$list->getBase("c"),"\n";
    Is better written as:
    Code:
    print '$list->getBase("c"): ', $list->getBase("c"), "\n";
    or, if you're using v5.10 or above
    Code:
    say '$list->getBase("c"): ', $list->getBase("c");
  4. #3
  5. No Profile Picture
    Contributing User
    Devshed Novice (500 - 999 posts)

    Join Date
    Jun 2012
    Posts
    830
    Rep Power
    496
    Not sure I understand what your problem is, but it seems that your other list is just a reference to the original list (same memory address), so that, in effect, you have only one list and two references to it.
  6. #4
  7. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Sep 2008
    Posts
    10
    Rep Power
    0
    Your posted module code is incomplete which prevents us from doing and testing.

    FishMonger you are right. My apologies.
    Here comes the whole module.


    ### doubleChained.pm

    PHP Code:
    ################################################################################
    package doubleChained;
    ################################################################################

    use strict;

    our $instances=0;
    our $first;
    our $last;

    sub new {
            
    my $invocant=shift(@_);
            
    my $class=ref($invocant) || $invocant;

            
    my $self={previous => undefnext => undefbase => undef, @_};

            if(
    $self->{objRef}) {

                    
    my $objRef=$self->{objRef};

                    if(
    $self->{inserteq "below") {
                            
    $first=$self if($first == $objRef);
                            
    $self->{previous}=$objRef->{previous};
                            
    $objRef->{previous}->{next}=$self if(defined($objRef->{previous}));
                            
    $objRef->{previous}=$self;
                            
    $self->{next}=$objRef;
                    } 
    elsif($self->{inserteq "above") {
                            
    $last=$self if($last == $objRef);
                            
    $self->{next}=$objRef->{next};
                            
    $objRef->{next}->{previous}=$self if(defined($objRef->{next}));
                            
    $objRef->{next}=$self;
                            
    $self->{previous}=$objRef;
                    }

                    
    delete($self->{insert});
                    
    delete($self->{objRef});
            } else {
                    
    $first=$self;
                    
    $last=$self;
            }

            
    bless($self,$class);
            
    $instances++;
            return(
    $self);
    }

    sub add {
            
    my $self=shift(@_);
            
    my %hash=@_;
            
    my $lookUpBase=$hash{base};
            
    my $objRef=$self;
            
    my $bkpObjRef;

            if((
    $lookUpBase cmp $objRef->{base}) == 0) {
                    return(
    undef);
            } 
    elsif(($lookUpBase cmp $objRef->{base}) == -1) {
                    return(
    doubleChained->new(objRef => $objRefinsert => "below"base => $hash{base})) unless(defined($objRef->{previous}));

                    while(
    defined($objRef->{previous})) {
                            
    $bkpObjRef=$objRef;
                            
    $objRef=$objRef->{previous};
                            return(
    undef) if(($lookUpBase cmp $objRef->{base}) == 0);
                            return(
    doubleChained->new(objRef => $objRefinsert => "below"base => $hash{base})) unless(defined($objRef->{previous}));
                            return(
    doubleChained->new(objRef => $bkpObjRefinsert => "below"base => $hash{base})) if(($lookUpBase cmp $bkpObjRef->{base}) != -1);
                    }
            } 
    elsif(($lookUpBase cmp $objRef->{base}) == 1) {
                    return(
    doubleChained->new(objRef => $objRefinsert => "above"base => $hash{base})) unless(defined($objRef->{next}));

                    while(
    defined($objRef->{next})) {
                            
    $bkpObjRef=$objRef;
                            
    $objRef=$objRef->{next};
                            return(
    undef) if(($lookUpBase cmp $objRef->{base}) == 0);
                            return(
    doubleChained->new(objRef => $objRefinsert => "above"base => $hash{base})) unless(defined($objRef->{next}));
                            return(
    doubleChained->new(objRef => $bkpObjRefinsert => "above"base => $hash{base})) if(($lookUpBase cmp $bkpObjRef->{base}) != 1);
                    }
            }
    }

    sub removeObject {
            
    my $self=shift(@_);

            
    $first=$self->{next} if($first == $self);
            
    $last=$self->{previous} if($last == $self);
            
    $self->{previous}->{next}=$self->{next} if(defined($self->{previous}));
            
    $self->{next}->{previous}=$self->{previous} if(defined($self->{next}));
            
    $self->{previous}=undef;
            
    $self->{next}=undef;
            return(
    $self);
    }

    sub previous {
            
    my $self=shift(@_);
            return(
    $self->{previous});
    }

    sub next {
            
    my $self=shift(@_);
            return(
    $self->{next});
    }

    sub first {
            
    my $self=shift(@_);
            return(
    $first);
    }

    sub last {
            
    my $self=shift(@_);
            return(
    $last);
    }

    sub getBase {
            
    my $self=shift(@_);
            
    my $base=shift(@_);
            
    my $objRef=$first;

            do {
                    return(
    $objRef) if($base eq $objRef->{base});
            } while(
    defined($objRef=$objRef->{next}));

            return(
    undef);
    }

    sub baseName {
            
    my $self=shift(@_);
            return(
    $self->{base});
    }

    sub DESTROY $instances--;}

    1
    What version of perl are you using?

    My version of Perl is v5.14.3
  8. #5
  9. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Sep 2008
    Posts
    10
    Rep Power
    0
    Originally Posted by Laurent_R
    Not sure I understand what your problem is, but it seems that your other list is just a reference to the original list (same memory address), so that, in effect, you have only one list and two references to it.

    Hello Laurent_R

    Exactly that is the point.
    If an object is removed from a list and returned by method removeObject it should be reusable to insert it into another list.
    So in the object to be removed from a list at first all references to other list objects (previous and next list object) must be undef-ed before it´s returned.
    But that is obviously not the case here.

IMN logo majestic logo threadwatch logo seochat tools logo