LISP lokale/Globale variable Zuordnung
Wenn wir eine Funktion definieren, die so etwas wie
(defun foo(x)
(setf x somevalue))
Ist x
definiert als eine lokale variable oder global??? mit setf/q ist der Wert global sein.
wenn es global ist, kann mir jemand sagen, wie definieren Sie eine lokale variable in lisp andere als let
?
Dank!
Betrachten Sie das folgende Beispiel
(let ((x 0))
(defun foo (y)
(when (equal x 0) (setq x y))
(when (< x y) (setq x y))
x))
wenn ich gebe ein wenig input zu foo
wie (foo 2)
es ist wieder 2 und wenn wir führen Sie die Funktion erneut mit (foo 1)
es noch gibt 2 zurück, und (foo 3)
3 gibt.Dies ist, was ich wirklich wollen, es zu tun.Aber die Frage ist, wie ist dies möglich, weil, wenn ich versuche, auf die variable x
außerhalb der Funktion aus der clisp-terminal, ich bin nicht in der Lage.Wenn ich Zugriff auf die Funktion erneut, es scheint, behalten den bisherigen Wert von x
.
danke!
Du musst angemeldet sein, um einen Kommentar abzugeben.
Parallelen zu ziehen zu anderen Sprachen wie C, C++, Java oder Python, was Ihr code änderungen ist eine "lokale variable", auch wenn dies nicht eine Formulierung, die ein Lisper verwenden würde (die Formulierung im Lisp-Jargon wäre eine lokale "Bindung").
Können Sie zum erstellen von lokalen Variablen durch die Verwendung von Funktionsparametern wie dein Beispiel ist, oder mit einige standard-Formen wie:
(let ((x 12)) ...)
(do ((x 0 (1+ i))) ...)
(dotimes (x 10) ...)
(loop for x from 0 to 10 do ...)
Auf der anderen Seite ist es möglich, dass bei Ihrer Umsetzung alle lokalen Variablen erzeugt werden, indem Parameter und andere Formen sind einfach Makros zu erweitern, dass. Zum Beispiel:
entspricht
Beachten Sie auch, dass in der Tat Lesen Sie Ihre code-fragment ist es möglich, dass
x
ist in gewissem Sinne eine "Globale variable", weil es hätte deklariert special:Wenn Sie eine variable deklarieren, die "special" mit
(defvar ...)
wird es anders gehandhabt werden: es ist wie jedes mal, wenn Sie es als parameter, oder verwenden Sie es in einem(let ..)
form, was der code tun ist, speichern Sie den aktuellen Wert mit dem neuen Wert zur Verfügung gestellt und dann wiederherstellen der Wert nach verlassen der Funktion oderlet
.Also diese Variablen sind sowohl "global" (weil die äußeren Funktionen, die Sie sehen kann), aber auch lokale (weil nach Ihrer Funktion oder lassen Sie beendet, wird der Vorherige Wert wiederhergestellt wird).
Der Konvention ist der name der speziellen Variablen, die mit "Ohrenschützer", d.h. mit einem Stern sowohl am Anfang und am Ende der Namen wie:
Dies hilft, wer liest deinen code zu verstehen, dass die variable special. Beachten Sie, dass dies jedoch nicht zwingend durch die Sprache und jeder name kann verwendet werden, für eine Besondere variable.
Es gibt nichts vergleichbares, um spezielle Variablen in C, C++, Java oder Python.
Einer letzten Anmerkung über
setq
undsetf
. Dinge sind ein bisschen schwierig hier, weil Sie müssen verstehen, den unteren Ebenen von Lisp um zu sehen, warumsetq
benötigt wird. Wenn Sie mit Common Lisp, dann sollten Sie einfach vergessensetq
und verwenden Sie immersetf
.setf
ist ein makro, das expandiert wirdsetq
bei Bedarf (jedoch auchsetq
ändern können, insetf
bei Bedarf (symbol Makros), und dies ist, wo die Dinge bekommen kann verwirrend für einen Neuling).Ihre Letzte Beispiel ist ein Fall einer "Schließung". Wenn Sie eine Funktion definieren (entweder benannt oder Unbenannt mit einem
(lambda ...)
form) kann die Funktion "capture", die Variablen, die sichtbar sind, und verwenden Sie Sie später. Ein einfacher Fall oft gezeigt wird, ist die "adder":diese Funktion liefert eine Funktion, halten das hinzufügen der übergebene Wert an einen internen Zähler:
ist die Ausgabe 13 (10 + 3), 22 (13 + 9) und 33 (22 + 11).
Die anonyme Funktion "eingefangen" wird die lokale variable
x
und können es auch nach dem beenden desadder
Funktion. In Sprachen wie C, C++ oder Java eine lokale variable kann nicht überleben, wenn Sie verlassen Sie den Bereich, der definiert die variable.C++11 hat Unbenannte Funktionen, aber immer noch Variablen nicht erfasst werden können und überleben den Rahmen (Sie kopiert werden kann auf lokale Variablen der Unbenannte Funktion, aber das ist nicht das gleiche).
(defun ...)
Formular innerhalb eines(let ...)
form? Wenn Sie Fragen zu common lisp im IRC-channel#lisp
hilfreich sein kann, die (webchat.freenode.net)lisp closure
.Vielen Dank für die Hilfe wieder 🙂((x) => {/*yay, I has a local binding */})(x)
?Eigentlich
x
ist lokal zur Funktion, sosetf
odersetq
ing, es ändert sich nur die lokale variablex
.Beantworten, den zweiten Teil Ihrer Frage, es ist ein weiterer Weg, um eine lokale variable definieren andere als gelassen:
In der Tat
defun
umgesetzt werden könntenobwohl alle Implementierungen, die ich geprüft habe mehr als das tun.
Auch, die
symbol-function
Ort ermöglicht es Ihnen, dies zu tun:aber das ist allgemein eine schlechte Idee.
Ihre zweite Frage
Was dort passiert, ist, dass
x
ist lokal auf den Bereich, der enthält diedefun
. Es ist nicht eine Globale variable. Was du tust mit, dassdefun
ist die Schaffung einer Schließung, die "fängt" alle die lexikalisch-Bereich (nicht mit erstelltdefvar
/defparameter
) Variablen in die umliegenden Bereiche und hält Sie für die Zukunft. Wenn Sie wollen, um zu überprüfen, den Wert derx
, fügen Sie eine weitere Funktioninnerhalb der
let
. Um es anders auszudrücken,x
lokalenlet
ist, dass die Funktion in. Die situation Sie haben die ähnlich ist:außer der inneren
let
wird ersetzt durch einedefun
(das ist einlambda
).In Ihrem code
x
ist ein parameter für dief
Funktion und somit lokal zu der Funktion. Der Aufrufsetf
erstellt keine neue variable, sondern stellt einfach den Wert der bestehenden lokalen Variablenx
. Mitsetq
stattsetf
würde dasselbe Verhalten.