http://qs321.pair.com?node_id=151941

Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

@retval is not returning $itm, it returns nothing at all... I wonder why??
#==================================================================== sub build_tree_for_cid($) { my ($cid) = @_; print "The cid we are seeking:"; print "$cid\n"; my $item = new Item; $item->id($cid); $item->type(-1); find_subs(\$item); return $item; } #==================================================================== sub find_subs(\$) { my ($item) = @_; print Dumper $$item; my $SQL; if ($$item->type == -1) { my $id = $$item->id; print "printing the item id\n"; print "$id\n"; $SQL = qq[SELECT uc.puid, up.prod_id FROM users_customers uc, user_products up WHERE ((uc.puid = up.puid) AND (uc.cid = $id) AND (up.from_date < SYSDATE) AND (up.to_date IS NULL OR up.to_date > SYSDATE))]; } else { my $id = $$item->id; print "printing the item id\n"; print "$id\n"; $SQL = qq[SELECT u.puid, up.prod_id FROM users u, user_products u +p WHERE ((u.puid = up.puid) AND (u.parent_puid = $id) AND (up.from_date < SYSDATE) AND (up.to_date IS NULL OR up.to_date > SYSDATE))]; } ${$item}->subs(my_execer($SQL)); print Dumper $$item; foreach my $subitem ($$item->subs) { find_subs(\$subitem); } return $item; } #==================================================================== sub my_execer($) { my ($sql) = @_; print "$sql\n"; my $sth = $dbh->prepare($sql) || undef; $sth->execute() || die "sth->execute: $DBI::errstr"; my @row; my @retval; if (@row = $sth->fetchrow_array) { my ($puid, $prod_id) = @row; print "printing weird stuff\n"; print "$puid\n"; print "$prod_id\n"; my $itm = new Item; $itm->id($puid); $itm->type($prod_id); print Dumper $itm; push (@retval,$itm); } $sth->finish; print "\@retval contains $#retval \n"; return (@retval); } #====================================================================

Replies are listed 'Best First'.
Re: bugs...
by tachyon (Chancellor) on Mar 15, 2002 at 11:12 UTC

    The sub my_excer does actually return @retval which contains the values from $itm. Your debugging print statements do not demonstrate this. Nor do you show the subs() method which you pass @retval to - this is probably where your problem lies as you seem to have enough print statements in your code to demonstrate that you are getting what you expect just before the return @retval. BTW you do not need to use prototypes for your subs the way you do. With $item you are passing a reference to a reference which is unnecessary and you then have to dereference it which make your code less clear.

    else { my $id = $$item->id; print "printing the item id\n"; print "$id\n"; $SQL = qq[SELECT u.puid, up.prod_id FROM users u, user_product +s up WHERE ((u.puid = up.puid) AND (u.parent_puid = $id) AND (up.from_date < SYSDATE) AND (up.to_date IS NULL OR up.to_date > SYSDATE))]; } my @RETVAL = my_execer($SQL); print "Hey I got something back!" if $#RETVAL > 0; print 'I got this back\n", Dumper(\@RETVAL); ${$item}->subs(@RETVAL); # <-- here is problem I think print Dumper $$item; foreach my $subitem ($$item->subs) { find_subs(\$subitem); } return $item;

    cheers

    tachyon

    s&&rsenoyhcatreve&&&s&n.+t&"$'$`$\"$\&"&ee&&y&srve&&d&&print

      Thanks for your answer, Aussie!:)
      # This snippet: $item->subs(my_execer($SQL)); # is just another way of writing my @tmp = my_execer($SQL); $item->subs(@tmp) # Here's the output <snip> printing weird stuff 1054226 426 $VAR1 = bless( [ 1054226, 426, [] ], 'Item' ); @retval contains 0 $VAR1 = bless( [ 50501948, -1, [] ], 'Item' ); $VAR1 = []; Can't call method "type" on unblessed reference at ./Caa.pl line 173. </snip>
      pretty frustrated norwegian girl...

        $#retval gives the index of the last element in the array. If an array is empty this will be -1. If it is zero then the array contains one element. Here is a demo:

        my @retval; print "the last index of \@retval is $#retval\n"; print "the number of *elements* in \@retval is ", scalar @retval, "\n" +; push @retval, 'one value'; print "the last index of \@retval is $#retval\n"; print "the number of *elements* in \@retval is ", scalar @retval, "\n" +; push @retval, 'another value'; print "the last index of \@retval is $#retval\n"; print "the number of *elements* in \@retval is ", scalar @retval, "\n" +;

        I fully understand the shorthand BTW ;-) The longhand is for your debugging benefit as your code craps out after this as you demonstrate! Also as noted you do not show the method where the error actually occurs. While using OO perl is a great idea your data structures are poor and do not take full advantage of the usual anonymous hash structure. Here is a very brief demo of how I might approach the problem:

        package Item; use Data::Dumper; my @items; # initialise an array of item objects from our data while (<DATA>) { chomp; next unless $_; my $item = new Item; my ($id, $quant ) = split ','; $item->id($id); $item->quant($quant); push @items, $item; } print Dumper \@items; # now sell one of each item for my $item (@items) { $item->quant(-1); } print Dumper \@items; # now print out the id and quantities print "\n\nid quant\n"; for my $item (@items) { print $item->id, "\t", $item->quant, "\n"; } ############################## sub new { my $self = shift; return bless {}, $self; } # get or set id sub id { my ($self, $cid) = @_; $self->{'id'} = $cid if defined $cid; return $self->{'id'}; } # get or set numbers in stock sub quant { my ($self, $change) = @_; $self->{'quant'} += $change if defined $change; return $self->{'quant'} } __DATA__ item 1,10 item 2,20 item 3,30

        cheers

        tachyon

        s&&rsenoyhcatreve&&&s&n.+t&"$'$`$\"$\&"&ee&&y&srve&&d&&print