Странный код Perl - поиск объяснений

Я знаю немного perl, но недостаточно глубоко понимаю следующее.

Чтение perldelta 5.18 я нашел следующий фрагмент кода, который уже отключен в 5.18. Не считая этого, все еще хотите понять, как это работает.

Вот код и в комментариях то, что я понимаю

%_=(_,"Just another "); #initialize the %_ hash with key=>value   _ => 'Just another'
$_="Perl hacker,\n";    #assign to the $_ variable with "Perl..."
s//_}->{_/e;            # darkness. the /e - evauates the expression, but...
print

он печатает:

Just another Perl hacker,

Я попробовал perl -MO=Deparse и получил следующий

(%_) = ('_', 'Just another ');   #initializing the %_ hash
$_ = "Perl hacker,\n";           # as above
s//%{'_';}/e;                    # substitute to the beginning of the $_ - WHAT?
print $_;                        # print the result
japh syntax OK

Что странно (по крайней мере для меня) - запуск кода "deparsed" не дает исходный результат и печатает:

1/8Perl hacker,

Я был бы очень доволен:

  • если кто-то может объяснить код, особенно если кто-то может написать вспомогательный код (с дополнительными шагами), что поможет мне понять, как оно работает - что происходит.
  • объясните, почему депарафинированный код не печатает исходный результат.

Что означает %{'_';} в отпарном коде?

Ответы

Ответ 1

Код, фактически выполняемый оператором подстановки, вероятно, фактически похож на

my $code = "do { $repl_expr }";

Итак, когда выражение замены _}->{_, выполняется следующее:

do { _}->{_ }

_ просто возвращает строку _ (так как strict выключен), так что то же, что и

do { "_" }->{_}

что совпадает с

"_"->{_}

У вас есть различие в хэш-элементе, где ссылка является символической ссылкой (т.е. строкой, а не фактической ссылкой). Обычно запрещается строгим, здесь приведен пример символической справки на работе:

%h1 = ( id => 123 );
%h2 = ( id => 456 );
print "h$_"->{id}, "\n"
   for 1..2;

Итак, это означает

"_"->{_}    # Run-time symbol lookup

совпадает с

$_{_}       # Compile-time symbol lookup

Подобный трюк часто используется в однострочном пространстве.

perl -nle'$c += $_; END { print $c }'

можно сократить до

perl -nle'$c += $_; }{ print $c'

Поскольку код, фактически выполняемый при использовании -n, получается из чего-то эквивалентного

my $code = "LINE: while (<>) { $program }";

%{'_';}

- очень странный способ записи

%{'_'}

который является разыменованием хэшей. Опять же, ссылка здесь является символической ссылкой. Это эквивалентно

%_

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