2012-07-24 10 views
11

Diciamo che ho una var speciale:modulo eval supposta per valutare una data forma in un ambiente lessicale nullo, non capisco quello che mi aspetto

(defvar x 20) 

poi faccio la seguente:

(let ((x 1)) (eval '(+ x 1)) 

che restituisce 2.

Secondo CLHS, eval "elabora forma nell'ambiente dinamico corrente e l'ambiente lessicale nullo". Quindi, mi aspetterei di ottenere 21 invece di 2.

Mi manca qualcosa?

Ora se non hanno vincolante per simbolo y dinamica, valutando

(let ((y 1)) (eval '(+ y 1)) 

ottengo condizione: "La variabile Y è libero", che ha senso, dato che non v'è vincolante per y dinamico.

Nota: sto usando SBCL 1.0.57

Apprezzare il vostro aiuto in anticipo!

risposta

7

nel tuo esempio x è special il che significa che è legato in un ambiente dinamica

y è non speciale, quindi è inevitabile che nell'ambiente lessicale


così al momento del primo eval gli ambienti potrebbero essere rappresentati in questo modo:

dynamic environment: { x : 1 } -> { x : 20, ...other global variables... } -> nil 
lexical environment: nil 

il simbolo x è speciale così eval alza gli occhi x nella corrente dinamica ambiente e trova x = 1


ammesso che è stato eseguito in stesso Lisp come l'ultimo esempio, l'ambiente della vostra Il secondo eval è il seguente:

dynamic environment: { x : 20, ...other global variables... } -> nil 
lexical environment: { y : 1 } -> nil 

il simbolo y è non speciale in modo eval alza gli occhi y nell'ambiente lessicale nullo - non l'ambiente lessicale corrente - e non trova niente.

questo ha senso quando ci si accorge che il lisp di solito è compilato e l'ambiente lessicale può essere ottimizzato in semplici istruzioni mov in alcuni casi.

+0

Questo aiuta molto! Apprezzo molto il tuo aiuto! – Svarog

5

DEFVAR dichiara le sue variabili speciali. Globalmente, ovunque. Non è inoltre possibile rimuovere facilmente questo.

Questo è anche il motivo non si dovrebbe mai usare nomi comuni come x, i, list come nomi di variabili per DEFVAR. Assicurati di utilizzare *x*, *i* e *list*. Altrimenti tutte le variabili, anche quelle locali, con questi nomi comuni sono dichiarate speciali.

+0

Sì, usare le cuffie con le variabili speciali è la migliore pratica supportata da tutti (me incluso, poiché rende il codice più chiaro), ma non l'autore del libro "Let Over Lambda" per evidenziare la dualità della sintassi. In questo caso particolare volevo vedere quale legame sarebbe stato raccolto dalla valutazione. Da quello che capisco dato che X è speciale, cambieremo il legame "globale" esistente di X a quello specificato da let form, ed è per questo che eval prende il valore di 1 appena rilegato da let. Per favore correggimi se ho capito male. – Svarog

+3

@Svarog: LET non modifica il binding globale. Crea una nuova associazione locale. In questo caso un legame dinamico. Dato che la X nel codice da valutare è automaticamente una variabile speciale (la dichiarazione DEFVAR ha effetto), EVAL usa l'associazione dinamica locale. –

Problemi correlati