Зачем вам нужен $ при доступе к элементам массива и хеша в Perl? - PullRequest
11 голосов
/ 30 сентября 2008

Поскольку массивы и хэши могут содержать только скаляры в 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 ]

22 голосов
/ 30 сентября 2008

Я только что использовал

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.

Это еще одна причина, по которой вам нужен сигил для доступа к массиву.

17 голосов
/ 30 сентября 2008

Ломтики не являются незаконными:

@slice = @myarray[1, 2, 5];
@slice = @myhash{qw/foo bar baz/};

И я подозреваю, что это одна из причин, почему вам нужно указать, хотите ли вы получить одно значение из хеша / массива или нет.

11 голосов
/ 30 сентября 2008

Сигил дает вам тип возврата контейнера. Поэтому, если что-то начинается с @, вы знаете, что оно возвращает список. Если он начинается с $, он возвращает скаляр.

Теперь, если после сигилы есть только идентификатор (например, $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 хочет знать во время компиляции, есть ли что-то в списке или в скалярном контексте, поэтому без начального символа некоторые термины станут неоднозначными.

9 голосов
/ 30 сентября 2008

Люди уже указали, что у вас могут быть фрагменты и контексты, но там есть сигилы, чтобы отделить вещи, которые являются переменными, от всего остального. Вам не нужно знать все ключевые слова или имена подпрограмм, чтобы выбрать разумное имя переменной. Это одна из самых больших вещей, которые мне не хватает в Perl на других языках.

9 голосов
/ 30 сентября 2008

Это допустимый Perl: @var[0]. Это кусок массива длиной один. @var[0,1] будет срез массива длиной два.

@var['key'] не является допустимым Perl, потому что массивы могут быть проиндексированы только по номерам, и два других (%var[0] and %var['key']) не являются допустимыми Perl, потому что срезы хеша используют {} для индексации хеша.

@var{'key'} и @var{0} являются допустимыми срезами хеша. Очевидно, что брать куски длиной один не нормально, но это, безусловно, допустимо.

См. раздел слайдов perldata perldoc для получения дополнительной информации о нарезке в Perl.

7 голосов
/ 30 сентября 2008

Я могу придумать, как

$x = myarray[1];

неоднозначно - что если вы хотите массив с именем m?

$x = m[1];

Как вы можете отличить это от соответствия регулярному выражению?

Другими словами, существует синтаксис, помогающий интерпретатору Perl, ну, в общем, интерпретировать!

6 голосов
/ 30 сентября 2008

В Perl 5 (подлежит изменению в Perl 6) символ указывает на контекст вашего выражения.

  • Вы хотите определенный скаляр из хеша, так что это $hash{key}.
  • Требуется значение определенного слота из массива, поэтому оно равно $array[0].

Однако, как указал Зигдон, срезы являются законными. Они интерпретируют эти выражения в контексте list .

  • Вы хотите списки из 1 значения в хэше @hash{key} works
  • Но также работают и большие списки, такие как @hash{qw<key1 key2 ... key_n>}.

  • Требуется пара слотов из массива @array[0,3,5..7,$n..$n+5] работает

  • @array[0] - список размером 1.

Не существует "хэш-контекста", поэтому ни %hash{@keys}, ни %hash{key} не имеют значения.

Итак, у вас есть "@" + "array[0]" <=> + в качестве полного выражения.

4 голосов
/ 30 сентября 2008

В Perl 5 вам нужны сигилы ($ и @), потому что интерпретация идентификатора голого слова по умолчанию - это интерпретация вызова подпрограммы (таким образом устраняется необходимость использовать & в большинстве случаев).

4 голосов
/ 30 сентября 2008

Символ предоставляет контекст для доступа:

  • $ означает скалярный контекст (скаляр переменная или отдельный элемент хеша или массива)
  • @ означает контекст списка (весь массив или фрагмент хеш или массив)
  • % - это целый хеш
...