Das ist falsch. Nicht eingeordnete Symbole sind Symbole, die in keinem Paket intern sind. Ansonsten sind sie vollkommen in Ordnung. intern bedeutet registriert in der Registrierung des Pakets für seine Symbole.
Der Leser macht Symbole durch ihren Namen nachzuschlagen, hier im aktuellen Paket:
(read-from-string "FOO") -> symbol `FOO`
ein zweites Mal:
(read-from-string "FOO") -> symbol `FOO`
es ist immer das gleiche Symbol FOO
.
(eq (read-from-string "FOO") (read-from-string "FOO")) -> T
#:FOO
ist die Syntax für ein uninterned Symbol mit dem Namen FOO
. Es ist in keinem Paket interniert. Wenn der Leser diese Syntax sieht, erstellt er ein neues Symbol ohne Unterbrechungen.
(read-from-string "#:FOO") -> new symbol `FOO`
ein zweites Mal:
(read-from-string "#:FOO") -> new symbol `FOO`
beiden Symbole unterschiedlich sind. Sie haben den gleichen Namen, aber sie sind verschiedene Datenobjekte. Es gibt keine andere Registrierung für Symbole als die Pakete.
(eq (read-from-string "#:FOO") (read-from-string "#:FOO")) -> NIL
So in Ihrem Fall (LET ((#:G4315 1)) (PRINT (INCF #:G4315)))
sind die uninterned Symbole verschiedene Objekte. Der zweite ist dann eine andere Variable.
Common Lisp hat eine Möglichkeit, Daten zu drucken, so dass die Identität während des Druckens/Lese erhalten ist:
CL-USER 59 > (macroexpand-1 '(test-macro))
(LET ((#:G1996 1)) (PRINT (INCF #:G1996)))
T
CL-USER 60 > (setf *print-circle* t)
T
CL-USER 61 > (macroexpand-1 '(test-macro))
(LET ((#1=#:G1998 1)) (PRINT (INCF #1#)))
T
Jetzt sehen Sie, dass die gedruckte s-expression ein Etikett #1=
für das erste Symbol hat . Es verweist dann später auf die gleiche Variable. Dies kann zurückgelesen werden und die Symbolidentitäten bleiben erhalten - obwohl das Lesegerät das Symbol nicht erkennen kann, wenn man das Paket ansieht.
So erstellt das Makro ein Formular, wo nur ein Symbol generiert wird. Wenn wir dieses Formular drucken und es zurücklesen wollen, müssen wir sicherstellen, dass die Identität der nicht-gebrauchten Symbole erhalten bleibt. Drucken mit *print-circle*
festgelegt auf T
hilft, das zu tun.
F: Warum wir uninterned erzeugten Symbole in Makros von GENSYM
mit (Symbol erzeugen)?
Auf diese Weise können wir einzigartige neue Symbole haben, die nicht mit anderen Symbolen im Code kollidieren. Sie erhalten einen Namen von der Funktion gensym
- in der Regel mit einer gezählten Nummer am Ende. Da es sich um frische neue Symbole handelt, die in keinem Paket enthalten sind, kann kein Namenskonflikt auftreten.
CL-USER 66 > (gensym)
#:G1999
CL-USER 67 > (gensym)
#:G2000
CL-USER 68 > (gensym "VAR")
#:VAR2001
CL-USER 69 > (gensym "PERSON")
#:PERSON2002
CL-USER 70 > (gensym)
#:G2003
CL-USER 71 > (describe *)
#:G2003 is a SYMBOL
NAME "G2003"
VALUE #<unbound value>
FUNCTION #<unbound function>
PLIST NIL
PACKAGE NIL <------- no package
Wenn ich Ihre Erklärung richtig verstanden hat, 'gensym' funktionieren würde nach wie vor richtig, auch wenn es nicht eine gezählte Anzahl auf den Namen des Symbols hinzugefügt hat, das heißt, wenn es ein uninterned Symbol mit dem gleichen Namen jedes Mal zurück es heißt (mit dem gleichen Argument). Ist das korrekt? Wenn ja: Warum fügt es die Nummer hinzu? Damit kann man leichter sagen, welche Symbole gleich sind und welche nicht in der Ausgabe von 'macro-expand' sind? – sepp2k
@ sepp2k: Korrekt, die Nummer dient nur dazu, zu erkennen, wo nicht-unterteilte Symbole unterschiedlich sind und welche die gleichen sein können. Es ist eine Debugging-Hilfe. In früheren Lisp-Dialekten (ohne Pakete) hätte es wichtiger sein können. –
Vielen Dank. Die * print-circle * Erklärung hilft wirklich zu verstehen, wie es funktioniert. Und danke für ein paar Erklärungen über nicht interpretierte Symbole. – JustAnotherCurious