Зачем вам нужен $ при доступе к элементам массива и хэша в Perl?

StackOverflow https://stackoverflow.com/questions/153644

  •  03-07-2019
  •  | 
  •  

Вопрос

Поскольку массивы и хэши могут содержать только скаляры в 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'};
Это было полезно?

Решение

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

@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: @var[0].Это фрагмент массива длиной один. @var[0,1] это был бы фрагмент массива длиной два.

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

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

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

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

Я могу придумать один способ, который

$x = myarray[1];

неоднозначно - что, если бы вам нужен был массив с именем m?

$x = m[1];

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

Другими словами, синтаксис предназначен для того, чтобы помочь интерпретатору Perl, ну, в общем, интерпретировать!

В Perl 5 (будет изменен в Perl 6) символ указывает на контекст о твоем выражении лица.

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

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

  • Вам нужен список из 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 вам нужны символы ($ и @), потому что интерпретация идентификатора bareword по умолчанию соответствует интерпретации вызова подпрограммы (таким образом, устраняется необходимость использования & в большинстве случаев ).

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top