2015-09-29 12 views
28

habe ich einen Code-Schnipsel gegeben gerade:Was ist "% _" in Perl?

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

Als Idiom für die Deduplizierung. Es scheint zu funktionieren, aber - es gibt keine %_ aufgeführt in perlvar.

Ich würde normalerweise die oben schreiben von %seen erklärt z.B .:

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

Aber %_ scheint zu stehen, obwohl es globale Reichweite zu sein scheint. Kann mir jemand eine Referenz dafür geben? (Oder zumindest beruhigen Sie mich, dass das oben genannte nichts Wichtiges zerschmettert!)

+9

Hier ist eine Diskussion darüber: http://www.perlmonks.org/?node_id=11757 –

+0

Intriguing. Kann also so einfach wie ein Überbleibsel des _ _ typeglob sein? Ich frage mich, ob es vor 15 Jahren noch etwas Neues gab. (Aber ich denke, wenn es sich nicht geändert hat, gibt es keinen Grund dafür). – Sobrique

+0

Nicht, dass Sie ein 'local% _;' im ersten Ausschnitt aus dem gleichen Grund benötigen, in dem Sie 'my% seen;' haben. – ikegami

Antwort

23

Es ist ein Hash. Sie können einen Hash mit dem Namen _ haben, da _ ein gültiger Name für eine Variable ist. (Ich bin sicher, Sie sind vertraut mit $_ und @_.)

Keine Perl gebautet derzeit setzt er oder liest %_ implizit, aber Interpunktionsvariablen wie %_ sind vorbehalten.

Perl von Variablennamen kann auch eine Folge von Ziffern oder eine einzelne Interpunktions oder Steuerzeichen (mit dem wörtlichen Steuerzeichenform veraltet) sein. Diese Namen sind alle reserviert für spezielle Anwendungen von Perl


Beachten Sie, dass Interpunktionsvariablen sind auch spezielle, dass sie „Super Globals“. Dies bedeutet, dass sich der unqualifizierte Code %_ im Root-Paket auf %_ bezieht und nicht auf %_ im aktuellen Paket.

$ 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! 

Das bedeutet, dass local %_ zu verwenden, zu vergessen (wie damals) sehr weitreichende Auswirkungen haben können.