Beefy Boxes and Bandwidth Generously Provided by pair Networks
XP is just a number

List assignment in scalar context

by Grimnebulin (Initiate)
on Jan 10, 2005 at 18:41 UTC ( #421035=perlquestion: print w/replies, xml ) Need Help??

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

I'm puzzled by the following bits of code:
$ perl -le '$n = () = split /,/, "1,2,3,4,5"; print $n' 1 $ perl -le '$n = ($a) = split /,/, "1,2,3,4,5"; print $n' 2 $ perl -le '$n = ($a, $b) = split /,/, "1,2,3,4,5"; print $n' 3 $ perl -le '$n = ($a, $b, $c) = split /,/, "1,2,3,4,5"; print $n' 4
This perlop man page states that "...a list assignment in scalar context returns the number of elements produced by the expression on the right hand side of the assignment." So, I would have expected each of the previous commands to print "5". What the heck is going on?

This is on perl 5.8.4.

Replies are listed 'Best First'.
•Re: List assignment in scalar context
by merlyn (Sage) on Jan 10, 2005 at 18:45 UTC
      Aha. Guess I should have RTFM. It contradicts my usually-accurate intuition about how list/scalar context works in Perl, so I hope I can be forgiven.

      My real-life code that inspired this question goes something like this:

      my $count = my ($arg1, $arg2, $arg3) = split /\s+/, $argstring; $count == 3 or die "3 arguments expected; you supplied $count\n";
      So if I want the real argument count, I have to split into a temporary array first, or else use a dummy trailing array in the assignment list. Gross.

      I can't say I care for this feature. Smells like premature optimization to me. And I notice it doesn't work across function calls. That could be a nasty surprise for someone someday.

        my $count = my ($arg1, $arg2, $arg3) = split /\s+/, $argstring, -1; # ^^^^

        - tye        

        So if I want the real argument count, I have to split into a temporary array first, or else use a dummy trailing array in the assignment list. Gross.

        Personally i think the issue here is that what you are trying to do is much less common than the opposite. Ie, more people would rather have split// be faster on spliting a few elements out scenarios than they would with have it be slower but more consistant with other list returning functions. After all, split may be quite the wrong way to do this. Arguably

        my $count=()=$argstring=~/\s+/g; my ($arg1, $arg2, $arg3) = split /\s+/, $argstring;

        is better anyway, as if the $argstring is long and you only are going to store three elements then its better not do the actual splitting (creating new svs, populating them etc) when you dont need to.


      That doesn't explain why the following happens:
      my ($a,$b,$c); my $n1 = ($a,$b,$c) = split /,/, "1,2,3,4,5"; my $n2 = my @x = ($a,$b,$c) = split /,/, "1,2,3,4,5"; print "$n1 ... $n2\n"; ---- 4 ... 3

      If it splits to one more, then why is that one going across one boundary, but not two?

      Being right, does not endow the right to be rude; politeness costs nothing.
      Being unknowing, is not the same as being stupid.
      Expressing a contrary opinion, whether to the individual or the group, is more often a sign of deeper thought than of cantankerous belligerence.
      Do not mistake your goals as the only goals; your opinion as the only opinion; your confidence as correctness. Saying you know better is not the same as explaining you know better.

        Oh come off it.

        sub list { return 1..5 } my ($a,$b,$c); my $n1 = ($a,$b,$c) = list(); my $n2 = my @x = ($a,$b,$c) = list(); print "$n1 ... $n2\n"; ---- 5 ... 3

        When you have scalar = list = list, you will always get the count of items in the rightmost list in scalar. In your $n2 example, your array is getting three items from the list. It isn't a scalar, so it isn't getting the count. What else would be expected? The behavior that merlyn is referring to is the reason why you don't see the complete count in the scalar.

        You tricked yourself.

        In the first case, the list assignment is evaluated in scalar context. In the second case, the list assignment is evaluated in list context and assigned to @x, yielding an array with three elements, which is then evaluated in scalar context. And an array with three elements evaluates to 3 in scalar context.

        Makeshifts last the longest.

Log In?

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://421035]
Approved by b10m
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others meditating upon the Monastery: (5)
As of 2021-09-22 12:55 GMT
Find Nodes?
    Voting Booth?

    No recent polls found