perl foreach Schleife mit Funktion Schließregeln

8

der folgende Code

%Vor%

tut nicht, was ich erwarten würde.

Was genau passiert? (Ich würde erwarten, dass es "test-0 \ ntest-1 \ ntest-2 \ ntest-3 \ ntest-4 \ n") ausgibt.

    
Snark 05.07.2011, 18:58
quelle

2 Antworten

19

Das Problem ist, dass das sub name {...} -Konstrukt nicht wie in einer for -Schleife verschachtelt werden kann.

Der Grund ist, weil sub name {...} wirklich BEGIN {*name = sub {...}} bedeutet und begin-Blöcke ausgeführt werden, sobald sie analysiert werden. Also erfolgt die Kompilierung und variable Bindung der Subroutine zur Kompilierungszeit, bevor die for-Schleife überhaupt ausgeführt werden kann.

Sie möchten eine anonyme Subroutine erstellen, die ihre Variablen zur Laufzeit bindet:

%Vor%

welches druckt

%Vor%

Vermutlich werden diese Closures in Ihrem echten Anwendungsfall in ein Array oder Hash geladen, damit sie später wieder aufgerufen werden können.

Sie können weiterhin Bareword-Bezeichner mit Closures verwenden, aber Sie müssen noch ein wenig mehr Arbeit verrichten, um sicherzustellen, dass die Namen zum Zeitpunkt der Kompilierung sichtbar sind:

%Vor%     
Eric Strom 05.07.2011, 19:05
quelle
7

Eric Strom's Antwort ist richtig und wahrscheinlich, was Sie sehen wollten, geht aber nicht auf die Details der Bindung ein.

Eine kurze Anmerkung zur lexikalischen Lebensdauer: Lexika werden zur Kompilierzeit erstellt und sind tatsächlich verfügbar, noch bevor ihr Gültigkeitsbereich eingegeben wurde, wie dieses Beispiel zeigt:

%Vor%

Danach, wenn sie den Gültigkeitsbereich verlassen, sind sie nicht mehr verfügbar, bis sie das nächste Mal in Reichweite sind:

%Vor%

In Ihrem Code ist der Abschluss zur Kompilierungszeit an das anfängliche lexikalische $i gebunden. Foreach Schleifen sind jedoch ein wenig seltsam; während my $i tatsächlich lexikalisch erzeugt, verwendet die foreach-Schleife es nicht; Stattdessen aliasiert es jede der Iterationen zu einem der überschleifen-Werte und stellt es dann nach der Schleife in seinen ursprünglichen Zustand zurück. Ihre Schließung ist also die einzige Sache, die auf das ursprüngliche lexikalische $i verweist.

Eine kleine Variation zeigt mehr Komplexität:

%Vor%

Hier wird das ursprüngliche $i zur Kompilierzeit erstellt und die Schließung bindet daran; Die erste Iteration der Schleife legt sie fest, aber die zweite Iteration der Schleife erstellt ein neues $i , das nicht mit dem Closure verknüpft ist.

    
ysth 05.07.2011 19:40
quelle

Tags und Links