Was ist der Unterschied zwischen "set", "setq" und "setf" in Common Lisp?
common-lisp
Richard Hoskins
quelle
quelle
Antworten:
Ursprünglich gab es in Lisp keine lexikalischen Variablen - nur dynamische. Und es gab kein SETQ oder SETF, nur die SET-Funktion.
Was ist jetzt geschrieben als:
wurde geschrieben als:
was schließlich mit SETQ (SET Quoted) abgekürzt wurde:
Dann passierten lexikalische Variablen, und SETQ wurde auch für die Zuweisung verwendet - es war also kein einfacher Wrapper mehr um SET.
Später erfand jemand SETF (SET Field) als generische Methode zum Zuweisen von Werten zu Datenstrukturen, um die l-Werte anderer Sprachen widerzuspiegeln:
würde geschrieben werden als
Aus Gründen der Symmetrie und Allgemeinheit stellte SETF auch die Funktionalität von SETQ bereit. Zu diesem Zeitpunkt wäre es richtig gewesen zu sagen, dass SETQ ein Grundelement auf niedriger Ebene und SETF eine Operation auf hoher Ebene war.
Dann passierten Symbolmakros. Damit Symbolmakros transparent funktionieren können, wurde erkannt, dass SETQ sich wie SETF verhalten muss, wenn die zugewiesene "Variable" wirklich ein Symbolmakro ist:
So kommen wir in der Gegenwart an: SET und SETQ sind verkümmerte Überreste älterer Dialekte und werden wahrscheinlich von späteren Nachfolgern von Common Lisp gebootet.
quelle
f
tatsächlich für Funktion und nicht für Feld (oder Form ) steht und Referenzen bereitstellt. Obwohl die Menge für Feld sinnvoll ist, sieht es so aus, als ob sie möglicherweise nicht korrekt ist.set
ist eine Funktion. Somit kennt es die Umgebung nicht.set
lexikalische Variable kann nicht angezeigt werden. Es kann nur den Symbolwert seines Arguments festlegen.setq
wird nicht mehr "gesetzt" gesetzt. Die Tatsache, dasssetq
es sich um eine spezielle Form und nicht um ein Makro handelt, zeigt dies.quelle
(setq ls '(((1))))
,(setf (car (car (car ls))) 5)
ist undefiniertes Verhalten, weil der Wert derls
Konstante (wie ein Stringliteral in C Modifizierung) ist. Nach dem(setq ls (list (list (list 1))))
,(setf (car (car (car ls))) 5)
funktioniert genauso wiels->val->val->val = 5
in Csetq
ist genau wieset
bei einem zitierten ersten Argument -(set 'foo '(bar baz))
ist genau so(setq foo '(bar baz))
.setf
Auf der anderen Seite ist es in der Tat subtil - es ist wie eine "Indirektion". Ich schlage vor, http://www.nano.com/lisp/cmucl-tutorials/LISP-tutorial-16.html als einen besseren Weg, um es zu verstehen, als jede Antwort hier geben kann ... kurz gesagt,setf
nimmt das erstes Argument als "Referenz", so dass zB(aref myarray 3)
(als erstes Argumentsetf
) ein Element innerhalb eines Arrays festgelegt wird.quelle
Sie können
setf
anstelleset
odersetq
aber nicht umgekehrt verwenden, da Siesetf
auch den Wert einzelner Elemente einer Variablen festlegen können, wenn die Variable einzelne Elemente enthält. Siehe die folgenden Beispiele:Alle vier Beispiele weisen die Liste (1, 2, 3) der Variablen mit dem Namen foo zu.
setf
hat die zusätzliche Möglichkeit, ein Mitglied der Listefoo
auf einen neuen Wert zu setzen.Sie können jedoch ein Symbolmakro definieren, das ein einzelnes Element in darstellt
foo
Sie können verwenden,
defvar
wenn Sie die Variable noch nicht definiert haben und ihr erst später in Ihrem Code einen Wert geben möchten.quelle
Man kann sich Konstrukte auf niedriger Ebene vorstellen
SET
undSETQ
diese sein.SET
kann den Wert von Symbolen einstellen.SETQ
kann den Wert von Variablen einstellen.Dann
SETF
gibt es ein Makro, das viele Arten von Einstellungsmöglichkeiten bietet: Symbole, Variablen, Array-Elemente, Instanz-Slots, ...Bei Symbolen und Variablen kann man denken, als würde man
SETF
sich inSET
und ausdehnenSETQ
.Also
SET
undSETQ
werden verwendet, um einige der Funktionen von zu implementierenSETF
, die das allgemeinere Konstrukt ist. Einige der anderen Antworten erzählen Ihnen die etwas komplexere Geschichte, wenn wir Symbolmakros berücksichtigen.quelle
Ich möchte zu früheren Antworten hinzufügen, dass setf ein Makro ist, das eine bestimmte Funktion aufruft, je nachdem, was als erstes Argument übergeben wurde. Vergleichen Sie die Ergebnisse der Makroerweiterung von setf mit verschiedenen Arten von Argumenten:
Für einige Arten von Argumenten wird "setf function" aufgerufen:
quelle