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

Hi,

I am a bit surprised by this:

my @a = ("a", "b"); my $x = @a; my $y = ("a", "b"); print "$x $y\n"; # prints "2 b"
I understand the first bit. I assign an array to a scalar, so the array is evaluated in scalar context, giving it's size, so $x is 2.

But the second bit is surprising to me...

I would have expected $y also to be 2, but instead the last element of the list is used instead (add more elements and you'll see it's always the last).

Is that intentional or documented somewhere (I am running 5.16.2)?

It certainly violates the principle of least surprise for me but maybe there is a good reason for this behaviour...

Can someone enlighten me?

Replies are listed 'Best First'.
Re: arrays and lists, hmmm
by Athanasius (Archbishop) on Apr 26, 2016 at 03:29 UTC

    Hello morgon,

    I would have expected $y also to be 2, but instead the last element of the list is used instead...

    But there is no list. I think what’s confusing here is that parentheses are used in Perl to make lists. But that only works in list context. In scalar context, as here, parentheses are only for grouping,1 which in this case makes no difference:

    13:20 >perl -wE "my $y = ('a', 'b'); say $y;" Useless use of a constant ("a") in void context at -e line 1. b 13:20 >perl -wE "my $y = 'a', 'b'; say $y;" Useless use of a constant ("b") in void context at -e line 1. a 13:20 >

    From perldata#List-value-constructors:

    List values are denoted by separating individual values by commas (and enclosing the list in parentheses where precedence requires it):
            (LIST)
    In a context not requiring a list value, the value of what appears to be a list literal is simply the value of the final element, as with the C comma operator.

    Update: 1Actually, parentheses are only used for grouping (precedence), regardless of context, as indicated in the perldata quote. My statement that parentheses are used to make lists is a little misleading: they are generally needed, but only because the assignment operator has higher precedence than the comma operator:

    14:05 >perl -MData::Dump -wE "my @a = 't'; dd \@a;" ["t"] 14:13 >perl -MData::Dump -wE "my @a = 't', 'u'; dd \@a;" Useless use of a constant ("u") in void context at -e line 1. ["t"] 14:13 >perl -MData::Dump -wE "my @a = ('t', 'u'); dd \@a;" ["t", "u"] 14:13 >

    Hope that helps,

    Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

      Very cool.

      I have always thought parentheses would create a list.

      Oh well, a life time is probably not enough to master perl (a quite dubious compliment though...).

Re: arrays and lists, hmmm
by beech (Parson) on Apr 26, 2016 at 02:34 UTC
Re: arrays and lists, hmmm
by Marshall (Canon) on Apr 26, 2016 at 03:58 UTC
    try this, the () forces list context and then after that, $y can be the number of elements.
    use warnings; use strict; my $y = () = ("a", "b"); print "$y\n"; __END__ Prints: 2
    Update: When writing this post, I knew that this "secret" operator had a cute name but I couldn't remember it. I found it: Goatse also called the "Saturn" operator, =()=.
Re: arrays and lists, hmmm
by haukex (Archbishop) on Apr 26, 2016 at 09:04 UTC

    Hi morgon,

    Personally I find the easiest way to think about this is by looking at the Comma Operator:

    In scalar context it evaluates its left argument, throws that value away, then evaluates its right argument and returns that value. ... In list context, it's just the list argument separator, and inserts both its arguments into the list. These arguments are also evaluated from left to right.

    And as Athanasius said, the parens are required because the assignment operator has higher precedence than the comma operator:

    $ perl -MO=Deparse,-p -e ' $x= "a","b" ' (($x = 'a'), '???'); $ perl -MO=Deparse,-p -e ' $x=("a","b") ' ($x = ('???', 'b'));

    Hope this helps,
    -- Hauke D

Re: arrays and lists, hmmm
by ikegami (Patriarch) on Apr 26, 2016 at 15:20 UTC
    Each operator gets to choose to what it evaluates in scalar context. See On Scalar Context for a sampling.