Присвоение контекста массива ссылке на пустой список в Perl, пожалуйста, объясните строку my @arr = [ ];

Я новичок в Перле. Я понимаю, что my @a = (); эквивалентно my @a;-- оба инициализируют пустой массив. Точно так же my $a = []; инициализирует пустой массив, на который ссылается $a.

Однако меня смущает my @arr = [];, который также является легальным Perl. Согласно ref() и print, @arr — это массив, а не ссылка на него. Его можно нажать, что, кажется, возвращает количество элементов в массиве. Но, похоже, он содержит ссылку на другой массив, который также можно вставить:

#!/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";

Выходы

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

Что здесь происходит? Детали очень ценятся.


person Max Wallace    schedule 07.03.2014    source источник
comment
Вы должны всегда use strict и use warnings в начале каждой программы Perl. В этом случае последний предупредил бы вас Scalar value @arr[0] better written as $arr[0]. В более поздних версиях Perl допустимо помещать в массив references, и первый элемент @arr является ссылкой. Для явного доступа к массиву вы должны написать @{ $arr[0] }.   -  person Borodin    schedule 07.03.2014
comment
[ ... ] примерно эквивалентно do { my @anon = ( ... ); \@anon }. Он возвращает ссылку, а ссылки являются скалярами и, следовательно, допустимыми значениями для элементов массива.   -  person ikegami    schedule 07.03.2014


Ответы (3)


Ваше понимание правильное.

[] всегда создает ссылку на массив, а ссылки всегда являются скалярами. Здесь my @arr = [] (или эквивалентно: my @arr = ([])) создает массив @arr, где первый элемент является ссылкой на массив.

Скаляры никогда не зависят от контекста! Контекст только важен для

  • хеш-переменные или массивы: @foo и %foo
  • вызовы подпрограмм, поскольку вызов распространяется на текущий контекст и может быть запрошен через wantarray. Поэтому подпрограммы могут вести себя по-разному в различных контекстах.
  • операторы, так как некоторые операторы, такие как , или .., полностью различаются в зависимости от контекста.
person amon    schedule 07.03.2014
comment
[] всегда создает ссылку на массив, кроме //, верно? - person bf2020; 07.03.2014
comment
@bf2020 квадратные скобки всегда обозначают ссылку на массив при использовании на уровне выражения. Конечно, они не имеют такого значения в строковых литералах "[0]" или регулярных выражениях /[0]/ или при использовании в качестве индексов массива $arr[0]. - person amon; 07.03.2014
comment
Принятие этого ответа, так как информация о контексте полезна. - person Max Wallace; 07.03.2014

@arr = [];

такой же как

@arr = ([]);

or

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

Он создает массив с одним элементом, ссылкой на пустой массив.


Заявления

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

создать массив с двумя элементами: ссылкой на пустой массив и скалярным значением 1, например

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

И, наконец, в заявлениях

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

первый аргумент эквивалентен $arr[0], ссылке на массив в этом примере. Поскольку Perl >=v5.14, функция push может работать как со ссылкой на массив, так и с самим массивом, поэтому эти операторы добавляют элементы к (изначально пустой) ссылке на массив, хранящейся в $arr[0]. Итак, теперь содержимое @arr эквивалентно тому, что вы получили бы, если бы сказали

@arr = ();
$arr[0] = [ 11, 12 ];     # ref to array with two elements
$arr[1] = 1;
person mob    schedule 07.03.2014

[] — это скалярное значение, которое является ссылкой на массив.

Этот:

my @arr = 42;

создает @arr как массив с одним элементом; значение этого элемента равно 42. Более четко написано так:

my @arr = ( 42 );

Очень похоже, что это:

my @arr = [];

также создает @arr как массив с одним элементом; значение этого элемента [], ссылка на массив. Более четко написано так:

my @arr = ( [] );

что означает то же самое.

Или, если вы действительно хотите, чтобы @arr был пустым массивом:

my @arr = ();

или, возможно, что-то вроде:

my $arr_ref = [];

(Возможно, к сожалению, скалярное значение в контексте массива рассматривается как одноэлементный список; я подозреваю, что путаница, которую это вызывает, превышает полезность этой функции.)

person Keith Thompson    schedule 07.03.2014