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
Обратите внимание, что присваивания выполняют копию, но псевдоним связывает имя с существующим скаляром.
undef
Perl имеет два типа 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
это взлом производительности, чтобы избежать копирования всего скаляра. Алиасинг намного дешевле, так как это подразумевает только копию одного указателя.