Массив Perl против списка

У меня есть две структуры данных в Perl:

Массив:

my @array2 = ( "1", "2", "3");

for $elem (@array2) {
    print $elem."\n";
}

Даю мне следующий вывод:

1
2
3

И список:

my @array = [ "1", "2", "3"];                                            

for $elem (@array) {
    print $elem."\n";
}

Давая следующий вывод:

ARRAY(0x9c90818)

Очевидно, я хотел бы перебирать элементы в обоих случаях, но почему второе решение дает мне только ссылку на этот массив?


person Marcin Cylke    schedule 16.05.2011    source источник


Ответы (6)


Списки в Perl не являются структурами данных, это позиции в исходном коде, определяемые контекстом вокруг них. Списки — это в основном временные структуры, которые Perl использует для перемещения данных. Вы взаимодействуете с ними со всем синтаксисом Perl, но вы не можете работать с ними как с типом данных. Наиболее близким к списку типом данных является массив.

my @var    =    (1, 2, 3);  # parens needed for precedence, they do not create a list
   ^ an array    ^ a list

say 1, 2, 3;
    ^ a list

say @var;
    ^ a list (of one array, which will expand into 3 values before `say` is called)

Когда вы пишете [1, 2, 3], вы создаете ссылку на скалярный массив. Эта ссылка на массив инициализируется списком 1, 2, 3, и это то же самое, что создать именованный массив и получить ссылку на него:

[1, 2, 3]   ~~   do {my @x = (1, 2, 3); \@x}

Поскольку конструкция [...] создает скаляр, вы должны хранить ее в скаляре:

my $array = [1, 2, 3];                                            

for my $elem (@$array) {   # lexical loop variable
    print $elem."\n";
}

Поскольку вы хотите работать со всем массивом, а не только со ссылкой, вы помещаете @ перед $array, что разыменовывает сохраненную ссылку на массив.

person Eric Strom    schedule 16.05.2011

Квадратные скобки используются для создания анонимного массива. При оценке он возвращает ссылку на этот массив, а не фактические значения массива.

Скобки не имеют такого скрытого свойства, а просто переопределяют приоритет внутри выражений, как и в математике. Например:

my @array = 1,2,3;

На самом деле оценивается так:

my @array = 1;
2,3; # causes the warning "Useless use of constant in void context"

потому что оператор = имеет более высокий приоритет, чем запятые. Поэтому, чтобы обойти это, мы используем круглые скобки при назначении массивов, например:

my @array = (1,2,3);

Ваш пример:

my @array = [1,2,3];

примерно так:

my @tmp = (1,2,3);
my @array = \@tmp;

Где \ используется для создания ссылки на массив @tmp.

person TLP    schedule 16.05.2011

Квадратные скобки создают анонимный массив, заполняют массив содержимым скобок и возвращают ссылку на этот массив. Другими словами,

[ "1", "2", "3" ]

в основном такой же, как

do { my @anon = ("1", "2", "3"); \@anon }

Таким образом, код должен выглядеть так

my $array_ref = [ "1", "2", "3" ];

for (@$array_ref) {  # Short for @{ $array_ref }
    print "$_\n";
}

or

my @array_of_refs = ([ "1", "2", "3" ]);

for my $array_ref (@array_of_refs) {
    for (@$array_ref) {
        print "$_\n";
    }
}
person ikegami    schedule 16.05.2011

Если вам нужны дополнительные разъяснения, см. соответствующую документацию.

Вы можете попробовать сделать некоторые вещи для иллюстрации:

#!perl -lw # -l appends a \n to each print, -w enables warnings
use strict;
my $aryref = [1 .. 5];
print for $aryref;    # Prints the stringified reference - not what you want
print for @$aryref;   # Dereferencing it lets you access the array
my @ary = $aryref;    # Probably not what you want
print for @ary;       # Stringified reference again
print for @{$ary[0]}; # Dereference the first array element (which holds the ref)
person Lumi    schedule 16.05.2011
comment
ссылка на соответствующую документацию кажется неработающей... или просто шутка? - person Wolf; 15.03.2017

В Perl массивы и списки, по сути, одно и то же, но во втором примере не используется ни то, ни другое. Квадратные скобки окружают массив ссылка (скалярное значение), а "присвоение" скаляра массиву с чем-то вроде my @array = $scalar эквивалентно my @array = ($scalar). Таким образом, единственным элементом @array во втором примере является ссылка на массив.

person jwodder    schedule 16.05.2011
comment
В Perl массивы и списки — не одно и то же, так же как скаляры и числа — не одно и то же. Один — переменная, другой — данные, которые можно хранить в этой переменной. Во втором примере список используется для указания содержимого создаваемого анонимного массива. Квадратные скобки создают ссылку на массив. После этого вы правильно поняли :-) - person tadmc; 17.05.2011

@array = ("1","2","3"); Здесь 1,2,3 — элемент переменной @array. Например $array[0] равно 1, $array[1] равно 2 и $array[2] равно 3.

@array = ["1","2","3"]; Perl использует ссылки на анонимные массивы с помощью [ ], поэтому здесь в основном хранится только один элемент, и это ссылка массив ["1","2","3"] в переменную @array. например, $array[0] - это "ARRAY(0x9c90818)"
Следовательно, при печати он показывает вам ссылки.

person Sandeep_black    schedule 30.03.2017