2013-06-01 3 views
14

Я знаю немного 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 

Что странно (по крайней мере для меня) - запуск «депаразированного» кода не дает исходного результата и пр. Интс:

1/8Perl hacker, 

Я был бы очень рад:

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

Что означает %{'_';} в тексте deparsed?

+2

Я не могу объяснить все, но почему-то '' _} -> {_ '' в регулярном выражении эквивалентно '' $ {_} {_} '' (который сам по себе выглядит забавным, но не тоже нечитабельно). – mzedeler

+0

Я не понимаю, как оператор стрелки каким-то образом поглощается, потому что он должен работать, только если '' $ _'' был хеш-ссылкой. – mzedeler

ответ

14

Код на самом деле выполняется оператором подстановки, вероятно, на самом деле что-то вроде

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

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

do { _}->{_ } 

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

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 }"; 

%{'_';} 

очень странно способ написать

%{'_'} 

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

%_ 

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

+0

Поскольку он пытается игнорировать 'do' или что-то еще, добавленное выражением replacment, но заканчивается тем, что игнорирует что-то еще, поскольку' do' уже не первый. – ikegami

+0

Или в более общих чертах код создает скомпилированный код, который никогда не должен существовать, поэтому допущение Deparse делает неудачу. – ikegami

Смежные вопросы