perl -Mstrict -wlE 'my %h; say grep 0, $h{poluted}; say keys %h'
Выход
poluted
и
perl -Mstrict -wlE 'my %h; say grep 0, my @r= $h{poluted}; say keys %h'
не выводит результат.
Я хотел бы знать, почему выходы разные?
perl -Mstrict -wlE 'my %h; say grep 0, $h{poluted}; say keys %h'
Выход
poluted
и
perl -Mstrict -wlE 'my %h; say grep 0, my @r= $h{poluted}; say keys %h'
не выводит результат.
Я хотел бы знать, почему выходы разные?
В Perl-строках цикла map, grep и for переменная $_ присваивается каждому текущему элементу. Пока $_ может быть только для чтения, он всегда представляет допустимое скалярное значение.
Например, следующий код умирает:
$_ = 1 for 1, 2, 3; # constants are read-only
но это работает:
my @nums = (1, 2, 3);
$_ = 1 for @nums; # @nums isn't read-only
Обратите внимание, что присваивания выполняют копию, но псевдоним связывает имя с существующим скаляром.
undefPerl имеет два типа undef:
Скаляр может быть установлен как undef. Например:
my $foo; # is this kind of undef
$foo = 1; # isn't undef any more
Специальный глобально уникальный скаляр, который представляет значение readonly undef, например. возвращается при доступе к индексу uninitialized array в контексте rvalue. В API Perl это &PL_sv_undef. Вы можете получить ссылку на это значение, например. \undef и может содержать псевдоним переменной.
Внутри хэш-записи выбираются с помощью hv_fetch или hv_fetch_ent. В качестве аргументов оба принимают хеш, ключ и флаг, сообщающий им, доступен ли доступ только для чтения.
Если это доступ только для чтения, и элемент не существует, возвращается нулевой указатель, который проявляется как значение undef в пространстве Perl. Это значение undef не связано с хешем. Ergo, not exists $hash{foo} означает not defined $hash{foo}.
Но если он не доступен только для чтения и элемент не существует, создается новая запись, которая затем возвращается. Тем не менее, эта запись первоначально undef, пока она не будет установлена на другое значение через назначение.
grep 0, $h{polluted}
Списки аргументов для строковых конструкций сглажены до $_. Если выражения в списке являются константами или подпрограммами, то ничего эффектного не происходит. Но когда они являются переменными доступом, это подразумевает доступ на чтение и запись.
Итак, чтобы получить значение $h{polluted}, Perl, очевидно, делает доступ в режиме чтения-записи. Если мы посмотрим на коды операций для этого выражения, мы действительно видим:
3 <0> pushmark s
4 <#> gv[*h] s
5 <1> rv2hv sKR/1
6 <$> const[PV "polluted"] s/BARE
7 <2> helem sKM/2 # <-- hash element access, "M" flag is set!
8 <@> grepstart K
9 <|> grepwhile(other->a)[t2] vK
a <$> const[IV 0] s
goto 9
M означает MOD, что означает доступ к lvalue/read-write.
В for -loops, имеющий $_, является псевдонимом текущего элемента, может быть действительно полезным. В map и grep это взлом производительности, чтобы избежать копирования всего скаляра. Алиасинг намного дешевле, так как это подразумевает только копию одного указателя.