2015-09-29 3 views
28

Я только что был дан фрагмент кода:Что такое "% _" в perl?

@list = grep { !$_{$_}++ } @list; 

Как идиомы для дедупликации. Кажется, что это работает, но - нет %_, перечисленных в perlvar.

Я обычно пишу выше, объявляя %seen .: например

my %seen; my @list = grep { not $seen{$_}++ } @list; 

Но %_, кажется, работает, хотя, как представляется, глобальный масштаб. Может ли кто-нибудь указать мне на нее ссылку? (Или, по крайней мере, успокойте меня, что выполнение вышеизложенного не разрушает что-то важное!)

+9

Вот несколько обсуждений по этому вопросу: http://www.perlmonks.org/?node_id=11757 –

+0

Интригующий. Итак, может быть так же просто, как оставить символ '_' typeglob? Интересно, есть ли что-то более недавнее, что 15 лет назад. (Но я думаю, если бы он не изменился, для этого не было бы причин). – Sobrique

+0

Не то, что вам понадобится «local% _;» в первом фрагменте по той же причине, что и «мой% увиденный», во втором. – ikegami

ответ

23

Это хэш. У вас может быть хеш с именем _, потому что _ является допустимым именем для переменной. (Я уверен, что вы знакомы с $_ и @_.)

Нет Perl встроенные в настоящее время устанавливает его или читает %_ неявно, но пунктуация переменные, такие как %_ зарезервированы.

Имена переменных в Perl также могут быть последовательностью цифр или одним символом пунктуации или управления (с буквенной формой символа управления, устаревшей). Эти имена все зарезервированы для специальных целей на Perl


Обратите внимание, что знаки препинания переменные также специальные в том, что они являются «супер Глобал». Это означает, что неквалифицированный %_ относится к %_ в корневом пакете, а не %_ в текущем пакете.

$ perl -E' 
    %::x = (name => "%::x" ); 
    %::_ = (name => "%::_" ); 
    %Foo::x = (name => "%Foo::x"); 
    %Foo::_ = (name => "%Foo::_"); 

    package Foo; 

    say "%::x = $::x{name}"; 
    say "%::_ = $::_{name}"; 
    say "%Foo::x = $Foo::x{name}"; 
    say "%Foo::_ = $Foo::_{name}"; 

    say "%x  = $x{name}"; 
    say "%_  = $_{name}"; 
' 
%::x = %::x 
%::_ = %::_ 
%Foo::x = %Foo::x 
%Foo::_ = %Foo::_ 
%x  = %Foo::x 
%_  = %::_  <-- surprise! 

Это означает, что забывают использовать local %_ (как вы это делали) может иметь очень далеко идущие последствия.

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