Dynamische und Lexikalische Variablen in Common Lisp
Lese ich das Buch "Practical Common Lisp" von Peter Seibel.
In Kapitel 6, "Variablen" - Abschnitte
"Lexikalische Variablen und Verschlüsse" und "Dynamisch, ein.k.ein. Spezielle Variablen".
http://www.gigamonkeys.com/book/variables.html
Mein problem ist, dass die Beispiele in beiden Abschnitten zeigen, wie (lassen Sie ...) kann Schatten Globale Variablen und nicht wirklich sagen, der Unterschied zwischen der Dynamischen und Lexikalische vars.
Verstehe ich, wie Verschlüsse arbeiten, aber ich weiß nicht wirklich, was ist so besonderes daran, lassen Sie uns in diesem Beispiel:
(defvar *x* 10)
(defun foo ()
(format t "Before assignment~18tX: ~d~%" *x*)
(setf *x* (+ 1 *x*))
(format t "After assignment~18tX: ~d~%" *x*))
(defun bar ()
(foo)
(let ((*x* 20)) (foo))
(foo))
CL-USER> (foo)
Before assignment X: 10
After assignment X: 11
NIL
CL-USER> (bar)
Before assignment X: 11
After assignment X: 12
Before assignment X: 20
After assignment X: 21
Before assignment X: 12
After assignment X: 13
NIL
Ich fühle mich wie es ist nichts besonderes Los hier. Die äußeren foo in bar Schritten die Globale x, und foo umgeben von lassen in bar Schritten den schattigen x. Was ist der big deal? Ich sehe nicht, wie soll es das erklären Sie den Unterschied zwischen lexikalischem und dynamischen vars. Aber das Buch geht noch weiter:
So, wie funktioniert das? Wie lässt
wissen, dass, wenn es bindet x es ist
soll, erstellen Sie eine dynamische Bindung
anstatt eine normale lexikalische Bindung?
Es weiß, denn der name wurde
erklärt besonderes.12 Die Namen der einzelnen
variable definiert mit DEFVAR und
DEFPARAMETER ist automatisch deklariert
Global besonderes.
Was sollte passieren, wenn lassen binden würde x Verwendung "normale lexikalische Bindung"? Alles in allem, was sind die Unterschiede zwischen dynamischer und lexikalische Bindung und, wie in diesem Beispiel besonderen im Hinblick auf die dynamische Bindung?
Du musst angemeldet sein, um einen Kommentar abzugeben.
Wenn eine variable ist lexikalisch Gültigkeitsbereich, das system schaut nach, wo die Funktion ist definiert um den Wert zu finden für eine freie variable. Wenn eine variable ist dynamisch scoped, das system schaut nach, wo die Funktion ist genannt, um den Wert für die freie variable. Variablen in Common Lisp sind alle lexikalischen standardmäßig; jedoch dynamisch Gültigkeitsbereich Variablen definiert werden können, auf der obersten Ebene mit defvar oder defparameter.
Ein einfacheres Beispiel
lexikalische scoping (mit setq):
dynamischen scoping (mit defvar):
Wie funktioniert das wissen lassen wenn eine variable lexikalische oder dynamische? Es nicht. Auf der anderen Seite, wenn foo geht um den Wert von X, wird es zunächst finden, der lexikalische Wert definiert, auf der obersten Ebene. Es überprüft dann, ob die variable soll dynamisch sein. Wenn es so ist, dann foo sieht an die aufrufende Umgebung, die in diesem Fall verwendet lassen Sie überschatten den Wert von X auf 4.
(Hinweis: dies ist eine starke Vereinfachung, aber es wird Ihnen helfen zu visualisieren, den Unterschied zwischen den verschiedenen scoping-Regeln)
Was ist Los?
Ihnen sagen: Gefühl, es ist nichts besonderes Los hier. Die äußeren
foo
imbar
Schritten die Globalex
, undfoo
umgeben vonlet
imbar
Schritten den schattigenx
. Was ist der big deal?Den Besondere das ist hier passiert, ist, dass
LET
kann Schatten den Wert der*x*
. Mit lexikalischen Variablen ist nicht möglich.Den code deklariert
*x*
werden Besondere über dieDEFVAR
.In
FOO
jetzt wird der Wert von*x*
gesucht wird dynamischer.FOO
Sie die aktuellen dynamische Bindung von*x*
oder, wenn es keine ist, ist das symbol Wert symbol*x*
. Eine neue dynamische Bindung kann zum Beispiel eingeführt werden, mitLET
.Einer lexikalischen variable auf der anderen Seite vorhanden sein muss, die lexikalische Umgebung irgendwo.
LET
,LAMBDA
,DEFUN
und andere vorstellen können, eine solche lexikalische Variablen. Sehen Sie hier die lexikalische variablex
eingeführt, die in drei verschiedene Arten:Wenn unser code:
Dann
X
waren Besondere in allen drei oben genannten Fällen, weil derDEFVAR
Erklärung, die erklärtX
werden Besondere - Global für alle Ebenen. Weil dieses, es ist die Konvention zu erklären Besondere Variablen als*X*
. Also nur Variablen mit Sternen um Sie herum sind Besondere - von übereinkommen. Das ist eine nützliche Konvention.In deinem code hast du dann:
Seit
*x*
hat erklärt Besondere über dieDEFVAR
oben in deinem code, dieLET
Konstrukt stellt eine neue dynamische Bindung für*x*
.FOO
wird dann aufgerufen. Da drinFOO
die*x*
verwendet dynamische Bindung, sucht er den Strom ein und findet, dass*x*
dynamisch gebunden20
.Den Wert einer Besondere variable findet sich in der aktuellen dynamischen Bindung.
Lokalen BESONDERER Erklärungen
Gibt es auch lokale
special
Erklärungen:Wenn die variable erklärt worden war Besondere durch eine
DEFVAR
oderDEFPARAMETER
, dann werden die lokalenspecial
Erklärung verzichtet werden kann.Einer lexikalischen variable direkt auf die variable verweist-Bindung:
Sehen wir es uns in der Praxis:
Hier werden alle Variablen lexikalische. In form 2 die
LET
wird shadow nicht derX
in unserer Funktionf
. Das kann es nicht. Die Funktion verwendet die lexikalisch gebundenen Variablen, eingeführt durch dieLET ((X 10)
. Rund um die rufen Sie mit einer anderen lexikalisch gebundenX
im form 2 hat keine Auswirkungen auf Funktion.Lassen Sie uns versuchen Besondere Variablen:
Was nun? Funktioniert das?
Es nicht!
Den erste form wird die Funktion aufgerufen und es versucht, den dynamischen Wert von
X
und es gibt keine. Wir bekommen eine Fehlermeldung in form 1:X
ungebunden ist, da es keine dynamische Bindung in Kraft.Form 2 funktionieren würde, da die
LET
mit derspecial
Erklärung stellt eine dynamische Bindung fürX
.Vielleicht wird in diesem Beispiel helfen.
Können Sie sagen, Ihre Lisp zu binden lokale Variablen dynamisch zu:
Schreiben Beispiel von PCL.
Noch eine weitere tolle Erklärung, die von Auf Lisp, Kapitel 2.5 Umfang:
Common Lisp ist ein lexikalisch Gültigkeitsbereich Lisp. Schema ist die älteste Dialekt mit lexikalischen Umfang; vor der Regelung, Dynamikumfang wurde als eines der entscheidenden Merkmale von Lisp.
Den Unterschied zwischen lexikalischem und dynamischen Umfang kommt darauf an, wie eine Implementierung befasst sich mit freien Variablen. Ein symbol ist gebunden in einem Ausdruck, wenn festgestellt wurde, als eine variable, die entweder durch die als parameter oder variable-binding Operatoren wie lassen und zu tun. Symbole, die nicht gebunden sind, sagte, um frei zu sein. In diesem Beispiel scope ins Spiel kommt:
Innerhalb der defun-Ausdruck ist x gebunden und y frei ist. Freie Variablen sind interessant, weil es nicht offensichtlich ist, was Ihre Werte sein sollen. Es gibt keine Unsicherheit über den Wert einer gebundenen variable—als-scope-test aufgerufen wird, wird der Wert von x sollte alles sein, was übergeben wird, als argument. Was aber soll der Wert von y? Diese Frage beantwortet der Dialekt Umfang zu Regeln.
In einem dynamisch scoped Lisp, um den Wert zu finden, der eine freie variable bei der Ausführung von-scope-test schauen wir zurück durch die Kette von Funktionen, die es aufgerufen. Wenn wir Sie finden eine Umgebung, wo y gebunden war, die Bindung von y wird die in-scope-test. Wenn wir keine finden, nehmen wir den globalen Wert von y. So, in einem dynamisch scoped Lisp, y hätte den Wert, den es hatte in der aufrufenden Ausdruck:
Mit dynamischen scope, es bedeutet nichts, dass y gebunden war um 7 bei der scope-test definiert wurde. Alles, was zählt, ist, dass y hatte einen Wert von 5 bei der scope-test aufgerufen wurde.
In einem lexikalisch Gültigkeitsbereich Lisp, anstatt auf der Suche zurück durch die Kette der aufrufenden Funktionen, wir blicken zurück, durch die mit Umgebungen an der Zeit die Funktion definiert wurde. In einem lexikalisch Gültigkeitsbereich Lisp, unserem Beispiel fangen würde, die Bindung von y-scope-test definiert wurde. Also das ist, was passieren würde, in Common Lisp:
Hier die Bindung von y auf 5 zu der Zeit des Anrufs hat keine Auswirkungen auf den zurückgegebenen Wert.
Obwohl Sie können immer noch dynamischen Gültigkeitsbereich durch die Deklaration einer variable besonderes zu sein, lexikalische Bereich ist der Standard in Common Lisp. Auf der ganzen, der Lisp-community scheint Sicht die übergabe von dynamischen Bereich mit wenig bedauern. Für eine Sache, die es verwendet, um führen zu schrecklich schwer bugs. Aber lexikalischen Umfang ist mehr als ein Weg zur Vermeidung von Fehlern. Wie der nächste Abschnitt zeigen wird, macht es auch möglich, einige neue Programmiertechniken.
(proclaim '(special symbol)
können Sie behaupten, ein symbol ist etwas besonderes.