4

I'm new to Perl. I understand that my @a = (); is equivalent to my @a;-- both initialize an empty array. Similarly, my $a = []; initializes an empty array that's referenced by $a.

However, I'm perplexed by my @arr = []; which is also legal Perl. According to ref() and print, @arr is an array, not a reference to one. It can be pushed onto, which seems to return the number of elements in the array. But it seems to contain a reference to another array, which can also be pushed onto:

#!/usr/bin/perl
use v5.16;

my @arr = [];
push(@arr, 1);

print join(", ", @arr) . "\n";

push(@arr[0], 11);
push(@arr[0], 12);

print "a[0]: " . join(", ", @{@arr[0]}) . "\n";

Outputs

ARRAY(0xd6ede8), 1
a[0]: 11, 12

What is going on here? Detail is greatly appreciated.

2
  • 3
    You must always use strict and use warnings at the start of every Perl program. In this case the latter would have warned you Scalar value @arr[0] better written as $arr[0]. In later versions of Perl it is valid to push to array references, and the first element of @arr is a reference. To access the array explicitly you would write @{ $arr[0] }. Commented Mar 7, 2014 at 16:51
  • 1
    [ ... ] is roughly equivalent to do { my @anon = ( ... ); \@anon }. It returns a reference, and references are scalars, and thus legitimate values for array elements. Commented Mar 7, 2014 at 16:56

3 Answers 3

10
@arr = [];

is the same as

@arr = ([]);

or

@arr = (); $arr[0] = [];

It creates an array with one element, a reference to an empty array.


The statements

@arr = [];
push @arr, 1;

create an array with two elements: a reference to an empty array, and the scalar value 1, like saying

@arr = ();
$arr[0] = [];
$arr[1] = 1;

And finally, in the statements

push(@arr[0], 11);
push(@arr[0], 12);

the first argument is equivalent to $arr[0], an array reference in this example. Since Perl >=v5.14, the push function can operate on an array reference as well as an array, so these statements are adding elements to the (initially empty) array reference held in $arr[0]. So now the contents of @arr are equivalent what you'd get if you said

@arr = ();
$arr[0] = [ 11, 12 ];     # ref to array with two elements
$arr[1] = 1;
Sign up to request clarification or add additional context in comments.

Comments

4

Your understanding is correct.

The [] always creates an array reference, and references always are scalars. Here, my @arr = [] (or equivalently: my @arr = ([])) creates an array @arr with the first element being an array reference.

Scalars are never context-dependent! Context only matters for

  • hash or array variables: @foo and %foo
  • subroutine calls, as a call propagates the current context and can be queried via wantarray. Subroutines may therefore behave differently in various context.
  • operators, as some operators like , or .. are entirely different depending on context.

3 Comments

[] always creates an array reference except inbetween //, right?
@bf2020 square brackets always denote an array reference when used on an expression level. Of course, they do not have this meaning in string literals "[0]" or regexes /[0]/ or when used as array subscripts $arr[0].
Accepting this answer, as the information about context is useful.
2

[] is a scalar value, which happens to be an array reference.

This:

my @arr = 42;

creates @arr as an array with a single element; that element's value is 42. It's more clearly written as:

my @arr = ( 42 );

Very similarly, this:

my @arr = [];

also creates @arr as an array with a single element; that element's value is [], an array reference. It's more clearly written as:

my @arr = ( [] );

which means the same thing.

Or, if you really wanted @arr to be an empty array:

my @arr = ();

or possibly something like:

my $arr_ref = [];

(It is perhaps unfortunate that a scalar value in array context is treated as a single-element list; I suspect that the confusion it causes exceeds the usefulness of the feature.)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.