Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

List Assignment in Scalar Context

A list assignment in scalar context returns the number of elements on the right hand side:

scalar(my ($hello, $there, $world) = (7,8)); #evaluates to 2

Why does it evaluate the right hand side and produce 2, instead of the newly defined list being evaluated and returning 3?

To me, it seems like $hello gets 7, $there gets 8, and $world gets undef, then that list is evaluated in scalar context, which would result in 3, as that is the number of elements in the list ($hello $there $world). It seems weird to me that context affects which part of the evaluated expression is returned:

my $greeting = (($hello, $there, $world) = (7,8)); #2

my @greeting = (($hello, $there, $world) = (7,8));
my $greeting_length = @greeting; #3
like image 248
Brian Avatar asked Feb 16 '12 07:02

Brian


2 Answers

It's documented to count the elements on the right in perlop (the last sentence in the Assignment Operators section):

Similarly, a list assignment in list context produces the list of lvalues assigned to, and a list assignment in scalar context returns the number of elements produced by the expression on the right hand side of the assignment.

The reason it works like that is so that you can write things like this:

while (my ($key, $value) = each %hash) { ... }

If it counted the number of elements on the left hand side of the assignment, that would be an infinite loop.

If you think about it, the number of elements on the left hand side is either the same as on the right hand side or it's a constant (when you're assigning to a list of scalars). In the first case, it makes no difference which side you count, and in the second case, counting the right hand side is more useful.

On the other hand, in list context the assignment operator returns the left hand list, because that's more useful. If you use it in a context that modifies the list elements, you want to modify the variables that were just assigned to.

Re: your comment In your example, (7,8) is a two-element list, which is why the assignment operator returns 2. When you assign a shorter list to a longer list of scalars, the right hand side is not "padded out" with undef before the assignment happens. Instead, any variables that did not have a value associated with them from the right hand list are reset to their default value. For a scalar variable, that's undef. For arrays, that's an empty array. For hashes, that's an empty hash.

like image 128
cjm Avatar answered Sep 22 '22 01:09

cjm


It seems weird to me that context effects which side is evaluated:

It doesn't. Both sides (operands) of the list assignment operator evaluated, and whether the list assignment is evaluated in scalar context or list context does not affect the evaluation of the operands whatsoever.

Whether a list assignment is evaluated in scalar context or list context only affects the value it returns.

I have previously created Scalar vs List Assignment Operator, which attempts to make clear the differences between the two assignment operators and how they behave in scalar and list context.

like image 32
ikegami Avatar answered Sep 23 '22 01:09

ikegami