Как может #?использоваться в разыменованном массиве без использования @? - PullRequest
0 голосов
/ 11 октября 2018

Массив в perl разыменовывается следующим образом:

my @array = @{$array_reference};

При попытке присвоить массив разыменованию без '@', например,

my @array = {$array_reference};

Perl выбрасываетошибка: «Нечетное количество элементов в анонимном хеше в строке ./sand.pl 22».Мы не можем присвоить его переменной массива, потому что Perl запутался в типе.

Так как же мы можем выполнить ...

my $lastindex = $#{$array_reference};

, если Perl пытается понять, что '{$array_reference} 'это тип массива?Для меня было бы больше смысла, если бы это выглядело так:

my $lastindex = $#@{$array_reference};

(несмотря на то, что выглядело намного ужаснее).

Ответы [ 4 ]

0 голосов
/ 11 октября 2018
$array[$index]
@array[@indexes]
@array
$#array

эквивалентно

${ \@array }[$index]
@{ \@array }[@indexes]
@{ \@array }
$#{ \@array }

Смотрите шаблон?Везде, где используется NAME массива, вы можете использовать BLOCK, который вместо этого возвращает ссылку на массив.Это означает, что вы можете использовать

${ $ref }[$index]
@{ $ref }[@indexes]
@{ $ref }
$#{ $ref }

Это показано в Синтаксис разыменования Perl .


Обратите внимание, что вы можете опустить curlies, если BLOCK содержитничего, кроме простого скаляра.

$$ref[$index]
@$ref[@indexes]
@$ref
$#$ref

Существует также синтаксис "стрелки", который считается более понятным.

$ref->[$index]
$ref->@[@indexes]
$ref->@*
$ref->$#*
0 голосов
/ 11 октября 2018

tl; dr: $#{$array_reference} соответствует синтаксису $#array.


{} перегружен многими значениями, и это именно то, что такое Perl.

Иногда {} создает анонимный хеш.Это то, что делает {$array_reference}, пытаясь создать хеш, где ключом является строковое значение $array_reference, что-то вроде "ARRAY(0x7fb21e803280)", а значения нет.Поскольку вы пытаетесь создать хеш с ключом и без значения, вы получаете предупреждение «нечетное количество элементов».

Иногда {...} представляет собой блок, подобный sub { ... } или if(...) { ... }, или do {...} и т. Д.

Иногда это пустой блок, например { local $/; ... }.

Иногда он указывает ключ хеша, например $hash{key} или $hash->{key}.

Перед определенными символами {} делает разыменование явным.Хотя вы можете написать $#$array_reference или @$array_reference, иногда вы хотите разыменовать что-то, что не является простым скаляром.Например, если у вас есть функция, которая возвращает ссылку на массив, вы можете получить ее размер в одну строку с $#{ get_array_reference() }.$#{$array_reference} соответствует синтаксису $#array.

$#{...} разыменовывает массив и получает индекс.@{...} разыменовывает массив.%{...} разыменовывает хеш.${...} разыменовывает скаляр.*{...} разыменовывает глобус.

Вы могли бы найти раздел об именах переменных и символах в современном Perl полезным, чтобы лучше увидеть шаблон.

Было быимеет больше смысла для меня, если это выглядело как ...

Есть много таких вещей.Perl существует с 1987 года. Многие из этих дизайнерских решений были приняты десятилетия назад.Код для определения того, что означает {}, особенно сложен.То, что вообще существует различие между массивом и ссылкой на массив, немного странно.

0 голосов
/ 11 октября 2018

Perl смущен типом

Perl пытается понять, что '{$ array_reference}' является типом массива

Хорошо,это не тип массива.Perl не "борется";у вас просто неправильные ожидания.

Общее правило (как объяснено в perldoc perlreftut): Вы всегда можете использовать ссылку в фигурных скобках вместоимя переменной.

Таким образом:

@array           # a whole array
@{ $array_ref }  # same thing with a reference

$array[$i]           # an array element
${ $array_ref }[$i]  # same thing with a reference

$#array           # last index of an array
$#{ $array_ref }  # same thing with a reference

С другой стороны, с

my @array = {$array_reference};

происходит то, что вы используете синтаксис для ссылки на хешконструктор, { LIST }.Предупреждение возникает потому, что в рассматриваемом списке должно быть четное количество элементов (для ключей и значений):

my $hash_ref = {
    key1 => 'value1',
    key2 => 'value2',
};

То, что вы написали, рассматривается как

my @array = ({
    $array_reference => undef,
});

, то естьмассив, содержащий единственный элемент, который является ссылкой на хеш, содержащий единственный ключ, который является строковой ссылкой (и имеет значение undef).

Синтаксическая разница между разыменованием и конструктором hashrefчто разыменование начинается с символа (например, $, @ или %), тогда как конструктор хеш-ссылки начинается с простого {.


Технически говоря, { } в синтаксисе разыменования представляет собой фактический блок кода:

print ${
    print "one\n";  # yeah, I just put a statement in the middle of an expression
    print "two\n";
    ["three"]  # the last expression in this block is implicitly returned
               # (and dereferenced by the surrounding $ [0] construct outside)
}[0], "\n";

По (надеюсь) очевидным причинам, никто в действительности не делает этого в реальном коде.

0 голосов
/ 11 октября 2018

Синтаксис

my $lastindex = $#$array_reference;

, который присваивает $lastindex индекс последнего элемента анонимного массива, ссылка на который находится в переменной $array_reference.

Код

my @ary = { $ra };  # works but you get a warning

не выдает «ошибку», а скорее предупреждение.Другими словами, вы получаете @ary с одним элементом, ссылкой на анонимный хеш.Однако в хэше должно быть четное количество элементов, поэтому вы также получите предупреждение, что это не так.

Ваша последняя попытка разыменовывает массив с помощью @{$array_reference} - который возвращает список , а не массив переменная .«Список» - это мимолетная коллекция скаляров в памяти (подумайте о копировании скаляров в стек, чтобы перейти в другое место);нет понятия «индекс» для такой вещи.По этой причине $#@{$ra} даже не анализируется, как предполагалось, и является синтаксической ошибкой.

Синтаксис $#ary работает только с переменной @ary, и затем существуетсинтаксис $#$arrayref.В общем случае вы можете написать $#{$arrayref}, так как curlies допускают произвольное выражение, которое оценивает ссылку на массив, но для этого нет никаких оснований, поскольку у вас есть переменная со ссылкой на массив.

Я бы согласилсялегко сказать, что большая часть этого синтаксиса требует некоторого привыкания, чтобы выразиться так.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...