Why does assigning a list reference to an array variable in Perl work?

Viewed 90

I have the following three assignments, of which the second one looks non-standard:

my $realRef = [1, 2, 3];
my @nonRef  = [4, 5, 6];
my $nonRef  = [7, 8, 9];

The second one should really be the following instead:

my @nonRef  = (4, 5, 6);

When printing, all three variables contain array references and especially the same named variables only differing in @ and $ don't share the same data or overwrite each other.

Ref: ARRAY(0x1fd6a8); $VAR1 = [
          1,
          2,
          3
        ];
Ref: ARRAY(0x6445d8); $VAR1 = [
          4,
          5,
          6
        ];
Ref: ARRAY(0x644740); $VAR1 = [
          7,
          8,
          9
        ];

Why is @nonRefcontaining an array reference at all? Is that stored in $nonRef of the symbol table entry for nonRef or something like that? And why do values of @nonRef and $nonRef don't overlap? Aren't both referencing the same symbol table entry only with different slots, ARRAY vs. SCALAR? Because both store references in the end, I would have expected that the same symbol table entry with the slot SCALAR is used.

Thanks!

2 Answers

The second one is the same as my @nonRef = ([4, 5, 6]) — that is, you're just putting your arrayref into $nonRef[0].

You are creating a one-element array that consists of a reference to an array.


However many scalars you assign to the array is how many elements the array will have.

my @a = 4;
# my @a;
# $a[0] = 4;

my @a = 4..6;
# my @a;
# $a[0] = 4;
# $a[1] = 5;
# $a[2] = 6;

[4, 5, 6] produces one scalar (a reference to an array), so my @nonRef = [4, 5, 6]; creates an array that contains one value (the reference).

my @nonRef = [4, 5, 6];
# my @nonRef;
# $nonRef[0] = [4, 5, 6];

Note the complete lack of parens in the above examples. Parens don't create any kind of value/variable like [] and {} do. They merely override precedence like in mathematics. They are by no means necessary on the right-hand side of an assignment to an array. The only reason we commonly see them on the right hand side of assignments is because

my @a = 4, 5, 6;

is equivalent to

( my @a = 4 ), 5, 6;   # Only assigns 4 to the array.

For a sub without prototypes,

f(@a)

is the same as

f($a[0], $a[1], ...)

So when you did

print(Dumper(@nonRef));

it's as if you did

print(Dumper($nonRef[0]));

I prefer to use

print(Dumper(\@nonRef));
Related