Question

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.

Était-ce utile?

La solution 2

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.

Autres conseils

@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;

[] 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.)

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top