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

Why doesn't $ret_val (scalar) in the following code get the value 4: the number of elements in the list returned by the test subroutine? What's happening here? ...

perl -e ' sub test { my @array = qw{ fish, chicken, pork }; return @array,1; } # $ret_val gets the value 1; $ret_val = test(); # @ret_val get each item in @array and the last # index in @ret_val is 1 @ret_val = test(); print $ret_val . "\n"; print @ret_val . "\n"; for ( @ret_val ) { print $_ . "\n" }; ' 1 4 fish, chicken, pork 1

Invulnerable. Unlimited XP. Unlimited Votes. I must be...
        GhodMode

Replies are listed 'Best First'.
•Re: subroutine list return
by merlyn (Sage) on Jun 24, 2003 at 18:03 UTC
    First, your qw{} is wrong. Don't use commas there. Warnings would have told you otherwise.

    Second, the subroutine's last expression (the return value) is evaluated in the context of the caller. The expression:

    my $ret_val = (@array, 1);
    doesn't assign 4 to $ret_val. It uses the comma operator to calcuate the elements of the list one by one, and then discards all but the last, thus returning 1 there.

    I have a column on context that you might find useful.

    -- Randal L. Schwartz, Perl hacker
    Be sure to read my standard disclaimer if this is a reply.

Re: subroutine list return
by Tomte (Priest) on Jun 24, 2003 at 18:04 UTC

    Because a list, as oposed to an array, in scalar context assignment returns the last value of the list.

    perldoc perldata:
    If you evaluate an array in scalar context, it returns the length of the array. (Note that this is not true of lists, which return the last value, like the C comma operator, nor of built-in functions, which return whatever they feel like returning.)

    regards,
    tomte


    Hlade's Law:

    If you have a difficult task, give it to a lazy person --
    they will find an easier way to do it.

Re: subroutine list return
by Mr. Muskrat (Canon) on Jun 24, 2003 at 18:10 UTC

    To add to what's already been said (fix your qw()), this can be fixed easily by pushing the 1 onto the array and then returning only the array.

    Something like:

    sub test { my @array = qw{ fish chicken pork }; # I assume it's not this simple + in your real script push @array, 1; return @array; }

Re: subroutine list return
by NetWallah (Canon) on Jun 25, 2003 at 02:45 UTC
    Agreed, chromatic - that is much cleaner.

    Thanks - always something to learn here.

Re: subroutine list return
by NetWallah (Canon) on Jun 25, 2003 at 01:06 UTC
    I don't believe Mr Muskrat's suggestion would work. You are still in a scalar context.

    If you really wanted to get the count of items in the array returned, you could do it thus:

    sub x{return qw/e f g h 31/}; $a= @{[x()]}; # Force array context when calling sub print $a This prints the value 5
    The trick with the "@{[]}" is described in perfunc, under the function "scalar".

      Ugh. How about something a little cleaner?

      my $count = () = x(); print "$count\n";