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

I was quite surprised to find that \() (ref to an empty list) and [] (ref to an empty array) are not the same. I can understand that an empty list can be used to initialize both an empty array and an empty hash, so there must be a difference, but it turns out that the empty list becomes a ref to 'undef', and not (as I expected) a ref to something empty:
use Data::Dumper; my $aap = \(); my $noot = []; print Dumper($aap); print Dumper($noot); __DATA__ $VAR1 = \undef; $VAR1 = [];
Can anybody explain the logic behind this or point me to the relevant piece of documentation (I've searched, but don't know what to look for exactly), so I don't fall into similar traps in the future?

Edit by tye, put [] in CODE tags so it doesn't "disappear"

Replies are listed 'Best First'.
Re: difference between \() and []
by duff (Parson) on Mar 24, 2004 at 17:34 UTC

    A list and an array are not the same. You can't take a reference to a list. The syntax \(...) is a shorthand way to take references to several variables at once. This is mentioned in perlref somewhere (look for "list")

Re: difference between \() and []
by kvale (Monsignor) on Mar 24, 2004 at 17:43 UTC
    In the statement
    my $aap = \();
    perl is assigning to $app in scalar context. So the reference operator \ creates a reference for every element in the list, and returns the last element. Since there are no elements, this is a reference to undef. Consider
    my @a = (1,2,3); my $b = 4; my $aap = \(@a,$b); print Dumper($aap); my $aap = \($b,@a); print Dumper($aap); __OUTPUT__ $VAR1 = \4; $VAR1 = [ 1, 2, 3 ];
    It is helpful to think of a list on the RHS as an initializer that can be evaluated in different contexts.

    -Mark

Re: difference between \() and [] (clarification)
by broquaint (Abbot) on Mar 24, 2004 at 18:43 UTC
    A list and an array are two different things. Lists are unbounded series of values, whereas an array is a bounded series of values. Arrays can either live anonymously or symbolically through a variable or variable container. Lists however, can be looked at as scalar values in an unbounded state, as seen in the right-hand side of a list context assignment, subroutine calling/returning (foibles acknowledged), iteration and slicing (and more, no doubt). However, in scalar context what might look like a list is really just the comma operator working on a series of values.

    Now, in the case of $aap you're creating a reference to nothing, since there's no such thing as a list in scalar context (in as much as one could admire a 'sunny night') and since perl can't create a reference to nothing, undef is used. On reflection it may seem a little odd that perl allows one to reference nothing, but such is the orthogonality of perl's syntax and (mostly) DWIM nature.

    HTH

    _________
    broquaint

    update: added last sentence

Re: difference between \() and []
by chromatic (Archbishop) on Mar 24, 2004 at 18:33 UTC

    At the risk of starting a huge, subtle argument, () does not create a list. (I can throw around the terms lvalue, rvalue, and context if you like, but I think you'll do better if you just keep my first sentence in mind.)

      Please do start the huge, subtle argument. 8)

      Is it that, in this rvalue-case, () makes its content evaluated in list context instead of creating a list? In that case I think I'm starting to get it.

        I'd say that parenthesis only group things on the right hand side of an expression. They can enforce list context on the left hand side of an expression, especially if it'd normally be a scalar expression.

        The only way I can keep my sanity in this regard is to repeat the following mantra: there is no such thing as a list in scalar context.

        An array in scalar context returns its length. A hash returns its number of buckets. The comma operator returns its right operand, as in  my $foo = (1,2,3); A subroutine returns whatever it wants to. Every Perl construct or operator that can be used in an expression does well defined, but sometimes different, things in scalar or list context. See List is a Four-Letter Word.

Re: difference between \() and []
by dragonchild (Archbishop) on Mar 24, 2004 at 18:21 UTC
    You're also confusing another concept - hashes are just lists that do something special with every other value. This is why my %x = (); and my @x = (); work correctly. (=> is just a glorified comma that stringifies its LHS, in case you're wondering.)

    And, it sounds like you didn't read the Camel book very closely. I'd suggest you take the time and (re)read it.

    ------
    We are the carpenters and bricklayers of the Information Age.

    Then there are Damian modules.... *sigh* ... that's not about being less-lazy -- that's about being on some really good drugs -- you know, there is no spoon. - flyingmoose

      At the risk of nit picking, hashes aren't lists, they're hashes. You can assign a list to both an array and a hash and they do what you mean, but that doesn't make either of them lists.. =]
Re: difference between \() and []
by leriksen (Curate) on Mar 25, 2004 at 00:34 UTC
    I like to think of the difference between lists and arrays thus

    • Lists are immutable, once constructed/created, you can't change them. You can copy them to another list, create new lists from parts of the original, etc. But you can't change the list.
    • Arrays are true variables - you shift off the front, push onto the back, splice out of the middle - change it anyway you want.

    So operations that modify the length of a 'list' require an array. The camel book says you can think of an array as a variable and a list as its values.

    Note that you can assign to an element of a list e.g.

    ($a, $b, $c) = @_;

    but you can never change that list - you can't add another value, delete a value to make a shorter list or make one of the elements refer to a different variable. It is forever a list of 3 variables, $a, $b and $c.

    +++++++++++++++++
    #!/usr/bin/perl
    use warnings;use strict;use brain;