Подтвердить что ты не робот

Что такое "% _" в perl?

Мне только что был предоставлен фрагмент кода:

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

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

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

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

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

4b9b3361

Ответ 1

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

Нет встроенного 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 %_ (как и вы) может иметь очень далеко идущие последствия.