[Edinburgh-pm] a Perl surprise

Nick oinksocket at letterboxes.org
Wed Jul 18 10:32:07 PDT 2012


On 18/07/12 16:05, Aaron Crane wrote:
>> A list (as opposed to an array) in scalar context evaluates the to *last*
>> element (a bit of another gotcha I happened to already know about).
> 
> There isn't really any such thing as a list in scalar context, at
> least in one reasonable analysis of how all this works.  Instead, this
> is about the behaviour of the comma operator: in list context, the
> comma operator constructs a list, while in scalar context, it discards
> the operand on its left-hand side and returns the operand on its
> right-hand side.
> 
> qw is defined to give you the same behaviour: it yields a list in list
> context, or the last element in scalar context).
> 
> My "no list in scalar context" claim may sound like nitpicking, but it
> matters for code like this:
> 
>   my @x = (10 .. 12);
>   my $y = (6, 7, @x);
> 
> Given that lists always flatten, treating the assignment to $y as a
> "list in scalar context" suggests that it would be the same as
> 
>   my $y = (6, 7, 10, 11, 12);
> 
> which would set $y to 12, as you've discovered.  But in fact, the
> sequence of events is:
> 
> - scalar-evaluate 6, 7 (by throwing away the 6)
> - scalar-evaluate 7, @x (by throwing away the 7)
> - scalar-evaluate @x (by returning its length)
> - scalar-assign that value (the length of @x) to my $y
> 
> so $y ends up containing 3, not 12.

Yes indeed, another potential surprise.  I hadn't thought of it in terms of the
"comma operator", and in fact I don't normally consider it an operator so much
as a piece of delimiting syntax.  I'll try and remember to.

I confess I don't find this particular behaviour of commas very useful in
practise, and it has the side-effect of the surprising behaviour we're
discussing.  I'm trying and failing to think of a case where it helps.  Can you
think of one?


>>   perl -le 'sub wtf { my @a = 6, 7, 8; @a }; print wtf;' # -> 6
>>   perl -le 'sub wtf { my $a = (6, 7, 8); $a }; print wtf;' # -> 8
> 
> I don't think your first example there shows what you think it does —
> the relative precedence of assignment and comma make it identical to
> 
> perl -le 'sub wtf { (my @a = 6), 7, 8; @a } print wtf'

Actually, that is in fact what I understood it to mean.  This example was meant
to show another case where the grammar rules are (in my opinion) surprising,
even having learnt them.  When would I ever want to silently discard the terms 7
and 8 like this? It seems more practical to either

 a) have Perl "DWIM" (and assign the values to the list),

or perhaps preferably,

 b) generate a syntax error (so I can alter it to be less ambiguous).

If I really wanted to have the terms 7 and 8 evaluated and the result discarded
(perhaps with some side effect) I would probably use semi-colons, not commas.



N


More information about the Edinburgh-pm mailing list