Массив 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)
Очевидно, что я хотел бы перебирать элементы в обоих случаях, но почему второе решение дает мне только ссылку на этот массив?
Ответы
Ответ 1
Списки в 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
, который разделяет ссылку на хранимый массив.
Ответ 2
Квадратные скобки используются для создания анонимного массива. Когда оценивается, он возвращает ссылку на этот массив, а не фактические значения массива.
Скобки не имеют такого скрытого свойства, но просто переопределяют приоритет внутри выражений, как и в математике. Например:
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
.
Ответ 3
Квадратные скобки создают анонимный массив, заполняют массив содержимым скобок и возвращают ссылку на этот массив. Другими словами,
[ "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";
}
или
my @array_of_refs = ([ "1", "2", "3" ]);
for my $array_ref (@array_of_refs) {
for (@$array_ref) {
print "$_\n";
}
}
Ответ 4
Если вы хотите получить дополнительные разъяснения, см. соответствующую документацию.
Вы можете попробовать и сделать некоторые вещи для иллюстративных целей:
#!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)
Ответ 5
В Perl массивы и списки - это, по сути, одно и то же, но ваш второй пример не использует. Квадратные скобки окружают ссылку массива (скалярное значение), а "назначение" скаляра массиву с чем-то вроде my @array = $scalar
эквивалентно my @array = ($scalar)
. Таким образом, единственным элементом @array
в вашем втором примере является ссылка на массив.
Ответ 6
@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. для ex $array [0] - "ARRAY (0x9c90818)"
Следовательно, при печати он показывает вам ссылки.