Зачем вам нужен $ при доступе к элементам массива и хеша в Perl?
Поскольку массивы и хэши могут содержать только скаляры в Perl, почему вы должны использовать $, чтобы сообщить интерпретатору, что значение является скаляром при доступе к элементам массива или хеша? Другими словами, если у вас есть массив @myarray
и хэш %myhash
зачем вам нужно делать:
$x = $myarray[1];
$y = $myhash{'foo'};
вместо того, чтобы просто делать:
$x = myarray[1];
$y = myhash{'foo'};
Почему вышесказанное неоднозначно?
Разве это не было бы незаконным кодом Perl, если бы это было что-то кроме $ в этом месте? Например, не являются ли все перечисленные ниже незаконными в Perl?
@var[0];
@var{'key'};
%var[0];
%var{'key'};
9 ответов
Ломтики не являются незаконными:
@slice = @myarray[1, 2, 5];
@slice = @myhash{qw/foo bar baz/};
И я подозреваю, что это одна из причин, почему вам нужно указать, хотите ли вы получить одно значение из хеша / массива или нет.
Я только что использовал
my $x = myarray[1];
в программе, и, к моему удивлению, вот что произошло, когда я запустил его:
$ perl foo.pl
Flying Butt Monkeys!
Это потому, что вся программа выглядит так:
$ cat foo.pl
#!/usr/bin/env perl
use strict;
use warnings;
sub myarray {
print "Flying Butt Monkeys!\n";
}
my $x = myarray[1];
Таким образом, myarray вызывает подпрограмму, передавая ей ссылку на анонимный массив, содержащий единственный элемент, 1.
Это еще одна причина, по которой вам нужен сигил для доступа к массиву.
Сигил дает вам тип возврата контейнера. Так что если что-то начинается с @
вы знаете, что он возвращает список. Если это начинается с $
, возвращает скаляр.
Теперь, если после сигилы есть только идентификатор (например, $foo
или же @foo
, тогда это простая переменная доступа. Если это сопровождается [
, это доступ к массиву, если за ним следует {
Это доступ по хешу.
# variables
$foo
@foo
# accesses
$stuff{blubb} # accesses %stuff, returns a scalar
@stuff{@list} # accesses %stuff, returns an array
$stuff[blubb] # accesses @stuff, returns a scalar
# (and calls the blubb() function)
@stuff[blubb] # accesses @stuff, returns an array
Некоторые человеческие языки имеют очень похожие понятия.
Однако многие программисты находят, что это сбивает с толку, поэтому в Perl 6 используется инвариантный символ.
В общем, компилятор Perl 5 хочет знать во время компиляции, есть ли что-то в списке или в скалярном контексте, поэтому без начального символа некоторые термины станут неоднозначными.
Люди уже отмечали, что у вас могут быть фрагменты и контексты, но сигилы существуют для того, чтобы отделить переменные от всего остального. Вам не нужно знать все ключевые слова или имена подпрограмм, чтобы выбрать разумное имя переменной. Это одна из самых больших вещей, которые мне не хватает в Perl на других языках.
Это действительный Perl: @var[0]
, Это фрагмент массива длины один. @var[0,1]
будет кусок массива длиной два.
@var['key']
не является допустимым Perl, потому что массивы могут быть проиндексированы только по номерам, а два других (%var[0] and %var['key']
) не являются допустимыми Perl, потому что срезы хеша используют {} для индексации хеша.
@var{'key'}
а также @var{0}
оба являются допустимыми фрагментами хеша, хотя. Очевидно, что брать куски длиной один не нормально, но это, безусловно, допустимо.
Посмотрите секцию среза perldata perldoc для получения дополнительной информации о нарезке в Perl.
Я могу придумать один способ, которым
$x = myarray[1];
неоднозначно - что если вы хотите массив с именем m?
$x = m[1];
Как вы можете отличить это от соответствия регулярному выражению?
Другими словами, синтаксис существует, чтобы помочь интерпретатору Perl, ну, в общем, интерпретировать!
В Perl 5 (подлежит изменению в Perl 6) символ указывает на контекст вашего выражения.
- Вы хотите определенный скаляр из хеша, так что это
$hash{key}
, - Вы хотите значение определенного слота из массива, так что это
$array[0]
,
Однако, как указывает zigdon, срезы являются законными. Они интерпретируют эти выражения в контексте списка.
- Вы хотите списки 1 значение в хеш
@hash{key}
работает Но и большие списки работают так же, как
@hash{qw<key1 key2 ... key_n>}
,Вы хотите пару слотов из массива
@array[0,3,5..7,$n..$n+5]
работает@array[0]
это список размером 1.
Там нет "хэш-контекста", поэтому ни %hash{@keys}
ни %hash{key}
имеет значение.
Так что у тебя есть "@"
+ "array[0]"
<=>
В Perl 5 вам нужны сигилы ($ и @), потому что интерпретация идентификатора голого слова по умолчанию - это интерпретация вызова подпрограммы (таким образом устраняется необходимость использовать & в большинстве случаев).
Символ предоставляет контекст для доступа:
$
означает скалярный контекст (скалярная переменная или отдельный элемент хеша или массива)@
означает контекст списка (целый массив или фрагмент хеша или массив)%
это целый хеш