2013-06-01 7 views
14

Ich weiß ein wenig Perl, aber nicht genug tief, um die nächste zu verstehen.Seltsame Perl-Code - Suche nach Erklärung

Lesen perldelta 5.18 Ich fand das nächste Stück Code, was bereits deaktiviert ist in 5.18. Ohne dies zu zählen, wollen Sie immer noch verstehen, wie es funktioniert. Hier

ist der Code und die Kommentare sind, was ich verstehen

%_=(_,"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 

druckt:

Just another Perl hacker, 

Ich habe versucht, die perl -MO=Deparse und erhalten die nächste

(%_) = ('_', '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 

Was ist seltsam (zumindest für mich) - das Ausführen des "entparsten" Codes gibt nicht das ursprüngliche Ergebnis und pr Ints:

1/8Perl hacker, 

Ich würde sehr glücklich sein:

  1. , wenn jemand den Code erklären kann, vor allem, wenn jemand einen Helfer Code schreiben kann, (mit zusätzlichen Schritten), was mir hilft zu verstehen, wie es funktioniert, ist - was geschieht.
  2. erkläre, warum der entartete Code das ursprüngliche Ergebnis nicht ausgibt.

Was bedeutet die %{'_';} in der DEPARSED-Code?

+2

Ich kann nicht alles erklären, aber aus irgendeinem Grund ist '_} -> {_' 'in der Regex gleichbedeutend mit $ {_} {_}' '(was für sich komisch aussieht, aber nicht zu unlesbar). – mzedeler

+0

Was ich nicht bekomme, ist, wie der Pfeiloperator irgendwie verschlungen wird, weil es nur funktionieren sollte, wenn '' _ _ _ ''eine Hash-Referenz ist. – mzedeler

Antwort

14

Der Code durch die Substitution Operator ist wahrscheinlich etwas ausgeführt eigentlich tatsächlich wie So

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

, wenn der Ersatz Ausdruck _}->{_ nach der ausgeführt wird: gibt

do { _}->{_ } 

_ einfach die Zeichenfolge _ (da strikt ist aus), so das ist das gleiche wie

do { "_" }->{_} 

die die gleichen wie

ist
"_"->{_} 

Was Sie haben ein Hash-Element dereferenzieren ist, wo die Referenz eine symbolische Referenz (d.h. eine Zeichenfolge anstelle einer tatsächlichen Referenz). Normalerweise durch strenge verboten, hier ist ein Beispiel für eine symbolische Referenz bei der Arbeit:

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

So bedeutet, dass

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

die gleiche wie

$_{_}  # Compile-time symbol lookup 
ist

Ein ähnlicher Trick ist, oft in Einzeilern verwendet.

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

kann

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

verkürzt werden, weil der Code tatsächlich ausgeführt wird, wenn -n verwendet wird, wird von etwas erhalten entspricht

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

%{'_';} 

ist ein sehr seltsam Weg zu schreiben

%{'_'} 

was ist eine Hash-Dereferenz. Auch hier ist die Referenz eine symbolische Referenz. Es ist äquivalent zu

%_ 

Im skalaren Kontext gibt Hash-Strom einen Wert, der einige Informationen über dieses Hash-Interna (oder einen falschen Wert, wenn leer) berichtet. Es gibt einen Vorschlag, es zu ändern, um stattdessen die Anzahl der Schlüssel zurückzugeben.

+0

Weil es versucht, das 'do' zu ignorieren oder was auch immer vom Ersatzausdruck hinzugefügt wurde, aber es ignoriert etwas anderes, da das' do' nicht mehr das erste Op ist. – ikegami

+0

Oder allgemeiner gesagt, der Code erstellt kompilierten Code, der niemals existieren sollte, so dass eine von Deparse getroffene Annahme fehlschlägt. – ikegami