I simboli possono essere internati in un pacchetto oppure no. Un simbolo internato in un pacchetto può essere cercato e trovato. Un simbolo senza indirizzo non può essere cercato in un pacchetto. Solo un simbolo di un certo nome può essere in un pacchetto. C'è solo un simbolo CL-USER::FRED
.
si scrive:
Quindi, per quanto ne so i simboli uninterned sono i simboli per i quali il valutatore does't creare-simbolo associazione dati internamente.
Questo è sbagliato. I simboli Uninterned sono simboli che non sono internati in alcun pacchetto. Altrimenti stanno perfettamente bene. internato significa registrato nel registro del pacchetto per i relativi simboli.
La s-espressione lettore fa utilizzare il nome del simbolo e il pacchetto per identificare i simboli durante la lettura . Se non esiste un tale simbolo, è internato. Se ce n'è uno, questo viene restituito.
il lettore non guardare in alto i simboli con il loro nome, qui nel pacchetto corrente:
(read-from-string "FOO") -> symbol `FOO`
una seconda volta:
(read-from-string "FOO") -> symbol `FOO`
è sempre lo stesso simbolo FOO
.
(eq (read-from-string "FOO") (read-from-string "FOO")) -> T
#:FOO
è la sintassi di un simbolo uninterned con il nome FOO
. Non è internato in nessun pacchetto. Se il lettore vede questa sintassi, crea un nuovo simbolo non integrato.
(read-from-string "#:FOO") -> new symbol `FOO`
una seconda volta:
(read-from-string "#:FOO") -> new symbol `FOO`
Entrambi i simboli sono differenti. Hanno lo stesso nome, ma sono oggetti dati diversi. Non c'è altro registro per i simboli, rispetto ai pacchetti.
(eq (read-from-string "#:FOO") (read-from-string "#:FOO")) -> NIL
Così nel tuo caso (LET ((#:G4315 1)) (PRINT (INCF #:G4315)))
, i simboli uninterned sono oggetti diversi. Il secondo è quindi una variabile diversa.
Common Lisp ha un modo per stampare i dati, in modo che l'identità è conservata durante la stampa/lettura:
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
Ora si vede che la s-espressione stampata ha un'etichetta #1=
per il primo simbolo . Successivamente, fa riferimento alla stessa variabile. Questo può essere riletto e le identità dei simboli vengono mantenute - anche se il lettore non è in grado di identificare il simbolo osservando il pacchetto.
Così la macro crea un modulo, in cui è generato un solo simbolo. Quando stampiamo quel modulo e vogliamo leggerlo, dobbiamo assicurarci che l'identità dei simboli non integrati sia preservata. La stampa con *print-circle*
impostata su T
aiuta a farlo.
D: Perché usiamo simboli generati uninterned nelle macro utilizzando GENSYM
(generano simbolo)?
In questo modo possiamo avere nuovi simboli unici che non si scontrano con altri simboli nel codice. Hanno un nome con la funzione gensym
- di solito con un numero conteggiato alla fine. Dal momento che sono nuovi simboli non inclusi in alcun pacchetto, non possono esserci conflitti di denominazione.
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
Se ho capito bene la tua spiegazione, 'gensym' sarebbe ancora funzionare correttamente anche se non aggiungere un numero contato al nome del simbolo, cioè se ha restituito un simbolo uninterned con lo stesso nome di volta in volta è chiamato (con lo stesso argomento). È corretto? In tal caso: perché aggiunge il numero? In modo che si possa più facilmente dire quali simboli sono uguali e quali non sono nell'output di 'macro-expand'? – sepp2k
@ sepp2k: corretto, il numero serve solo per individuare facilmente dove i simboli non integrati sono diversi e quali potrebbero essere gli stessi. È un aiuto per il debug. Nei dialetti Lisp precedenti (senza pacchetti) avrebbe potuto essere più importante. –
Grazie mille. La spiegazione del * print-circle * è davvero utile per capire come funziona. E grazie per qualche spiegazione sui simboli noninterpretati. – JustAnotherCurious