Unterschied zwischen LET und SETQ?
Ich bin der Programmierung unter Ubuntu mithilfe von GCL. Aus den Unterlagen, die auf Common Lisp aus verschiedenen Quellen, die ich verstehe, dass let
erstellt lokalen Variablen, und setq
legt die Werte bestehenden Variablen. In nachstehenden Fällen, die ich brauche, um erstellen Sie zwei Variablen und die Summe Ihrer Werte.
Mit setq
(defun add_using_setq ()
(setq a 3) ; a never existed before , but still I'm able to assign value, what is its scope?
(setq b 4) ; b never existed before, but still I'm able to assign value, what is its scope?
(+ a b))
Mit let
(defun add_using_let ( )
(let ((x 3) (y 4)) ; creating variables x and y
(+ x y)))
In beiden Fällen, die ich scheinen das gleiche Ergebnis zu erzielen; was ist der Unterschied zwischen der Verwendung setq
und let
hier? Warum kann ich nicht mit setq
(da es syntaktisch leicht) in allen Orten, wo ich let
?
Du musst angemeldet sein, um einen Kommentar abzugeben.
setq
weist einer variable einen Wert zu, währendlet
führt neue Variablen/Bindungen. E. g., schauen Sie, was passiert inDen äußeren
let
wird eine lokale variable erstelltx
, und die innerelet
erstellt eine lokale variable shadowing die innere. Beachten Sie, dass die Verwendunglet
um Schatten, die variable hat keinen Einfluss auf den Schatten-variable, die den Wert; derx
im Einklangd
ist diex
eingeführt, die durch die äußerenlet
, und sein Wert hat sich nicht verändert.setq
wirkt sich nur auf die variable, mit der es aufgerufen wird. Dieses Beispiel zeigtsetq
verwendet, die mit lokalen Variablen, kann es sich aber auch mit speziellen Variablen (d.h., dynamisch scoped, und in der Regel definiert, mitdefparameter
oderdefvar
:Beachten Sie, dass
setq
nicht (portabel) erstellen Variablen, in der Erwägung, dasslet
,defvar
,defparameter
, &c. tun. Das Verhalten vonsetq
wenn man es mit dem argument, dass nicht eine variable (noch) nicht definiert, und es ist bis zu einer Umsetzung zu entscheiden, was zu tun ist. Zum Beispiel, SBCL beschwert sich lautstark:Natürlich, die besten Möglichkeiten, um ein besseres Verständnis dieser Konzepte sind zu Lesen und zu schreiben, mehr Lisp-code (das kommt mit der Zeit) und Lesen Sie die Einträge in der HyperSpec und Folgen Sie den Querverweisen, vor allem der Glossar-Einträge. E. g., die kurzen Beschreibungen aus dem HyperSpec für
setq
undlet
gehören:SETQ
LASSEN
Können Sie mehr Lesen möchten über Variablen und Bindungen.
let
undlet*
haben auch einige spezielle Verhalten mit dynamische Variablen undspecial
Erklärungen (aber Sie wahrscheinlich nicht brauchen, um zu wissen, dass für eine Weile), und in bestimmten Fällen (die Sie wahrscheinlich nicht brauchen, zu wissen, über für eine Weile) wenn eine variable nicht eigentlich eine variable,setq
ist eigentlich äquivalent zusetf
. Die HyperSpec hat mehr details.Gibt es einige nicht ganz doppelte Fragen auf Stack Overflow, die dennoch Hilfe zu verstehen, die Verwendung der verschiedenen Variablen definition und Zuordnung von Operatoren zur Verfügung, die in Common Lisp:
setq
auf Undefinierte Variablen)setq
's ein Undefiniertes symbol, wie es geschieht, Sie gehen noch weiter und definieren die symbol, die das beschriebene Verhalten in @wvxvw Antwort, wennadd_using_setq
ausgeführt wird. Dieses Verhalten ist zwar in der Norm nicht gefordert, es hat eine lange Geschichte. Ich habe alte Lehrbücher, die Sie lehren, um zu definieren, Globale Variablen mitsetq
.setq
außerhalb der top-Ebene haben eine lange Geschichte der Verwendung. Vielleicht auch nicht.Lassen, sollte fast immer so, wie Sie bind-Variablen innerhalb einer Funktion definition-außer in dem seltenen Fall, wo Sie wollen den Wert auch für andere Funktionen im selben Umfang.
Ich mag die Beschreibung der emacs-lisp-Handbuch:
(setq x y)
weist einen neuen Werty
auf die variable mit dem symbol gekennzeichnetx
Optional und definiert eine neue Paket-level-variable 1. Dies bedeutet, dass, nachdem Sie genanntadd_using_setq
Sie haben zwei neue Paket-level-Variablen in dem aktuellen Paket.drucken
3 4
- unwahrscheinlich, dass das gewünschte Ergebnis erzielt wird.Kontrast, dass, wenn Sie
let
Sie nur neue Werte zuweisen Variablen bezeichnet durch die Symbole, die für die Dauer der Funktion, so wird dieser code zu einem Fehler führen:Denken
let
als gleichwertig zu dem folgenden code:Als ein beiseite, die Sie wirklich wollen, schauen Sie in code geschrieben von anderen Programmierern, um eine Idee zu bekommen, wie name oder format Dinge. Neben traditionellen es hat auch einige typografische Eigenschaften, die Sie nicht wirklich wollen, zu verlieren.
1 Das Verhalten ist nicht standard, aber dies ist, was passiert in vielen gängigen Implementierungen. Unabhängig davon, dass es ziemlich vorhersehbar ist, ist es als schlechte Praxis aus anderen Gründen, die meist alle die gleichen Bedenken, die davon abhalten, die Sie aus der Verwendung von globalen Variablen.
setq
wird verwendet, um einen Wert zuweisen, der die toa-variable und eine variable kann lokal sein (lexical scope, z.B. mitlet
und nicht deklariertspecial
) oder global (z.B., definiert mitdefparameter
oderdefvar
.setq
wenn eine variable nicht definiert nicht definiert Verhalten. Es ist implementierungsabhängig, und es portable Programme können nicht auf Sie verlassen. E. g., siehe Rainer Joswig Antwort zu einer anderen Frage: "Es ist erforderlich für portable code, setzt man Variablen sind bereits erklärt. Die genaue Wirkung der Einstellung eine nicht deklarierte variable ist nicht definiert durch die Norm."setq
zu werfen. Ich werde formulieren Sie die Antwort, um diese zu reflektieren.(setq foo::x 34)
definieren Sie eine spezielle variable, dann wird das symbolfoo::x
überall zugänglich ist. (Nicht versuchen, allzu pingelig sein, aber Lockersetq
undlet
) verursachen andere Probleme die Straße hinunter. Pakete und symbol der Zugänglichkeit kann schwierig sein, genug für den erfahrenen Common Lisper; bilden eines falschen mentalen Modell schon früh konnte führen zu einige Kopfschmerzen später.foo::x
wäre noch ein "Paket-level" - variable, nur das Paketfoo
. Ich glaube nicht, dass nannte es ein "special" variable sehr informative: wer weiß, was ist das Besondere daran? Der Begriff ist so vage, dass nicht einmal Google wird Ihnen helfen, Sie vielleicht nicht einmal bemerken, dass es einen speziellen Begriff. Ich denke, das ist ein problem semantischer Natur, das verwandelt jede definition in einem Zen-koan 🙂 Hyperspec erwähnt auch eine Möglichkeit der Anwendungsetq
Symbole, die auf eine spezielle makro-expansion-Funktionen, die machen würde, die Erklärung noch weniger verständlich.hyperspec "special variable"
. 🙂let
und einer begleitendenspecial
Erklärung?special
Erklärung in der Art und Weise Sie sich das vorstellen. Sie können grep einfach beliebigen code auf Github zu bekommen überzeugt.special
kam später als Formsache, der hilft, diese Aufgabe.special
über diese Variablen, d.h. Sie sind dynamische Variablen, dielet
s ändern Sie Ihren Wert für diejenigen, dielet
s' dynamische Umfang, anstatt Ihre lexikalischen scope. Ein besseres Verständnis ist, dassdefvar
unddefpackage
Global definieren Sie ein symbol, wie der name einer Variablen ist, und dass (interniert) die Symbole gehören zu Paketen (und es würde nicht viel Sinn eine uninterned symbol für den Namen einer Variablen).global
.) Es gibt einen Weg, um zu beschreiben, diese Variablen als "Präfix " global", und das wäre gleichbedeutend mit dem Aufruf unser Thema "spezielle Variablen" basiert auf dem Konzept, dass die zur Durchführung der gewünschten Funktion ein Zauber ausgeführt wurde, auf ein symbol, das kennzeichnet Variablen, so dass die Umgebung entsprechend verarbeiten. Eine andere, allgemeinere Weise zu beschreiben, die situation ist zu sagen, dass die variable "global", oder "Modul-Niveau", die Ihnen sagt, was Sie tut, eher dann, wie es umgesetzt wird.können Sie den Wert des symbols aus dem Rahmen, so lange wie Lisp ist, der noch läuft. (es weisen Sie den Wert auf das symbol)
können Sie nicht bekommen, den Wert des symbols definiert ist, LASSEN Sie nach Lisp abgeschlossen hat, die Evaluierung der form. (es binden Sie den Wert auf das symbol, und erstellen Sie neue binding-symbol)
betrachten das Beispiel: