Ambito variabile + eval in Clojure

In Clojure,

(def x 3) (eval '(prn x)) 

stampa 3, mentre

 (let [y 3] (eval '(prn y))) 

e

 (binding [z 3] (eval '(prn z))) 

genera un’eccezione ‘Imansible risolvere var’.

Secondo http://clojure.org/evaluation , eval , load-string , ecc generano namespace temporanei per valutarne il contenuto. Pertanto, non mi aspetto che nessuno dei suddetti esempi di codice funzioni, poiché (def x 3) viene eseguito nel mio attuale spazio dei nomi, non quello creato da eval .

  1. Perché il primo esempio di codice funziona e non gli ultimi due?
  2. Come posso eval una forma con variabili associate senza usare def ?

Grazie!

1 .:

Il motivo per cui questo non funziona è (più o meno) indicato nella pagina che hai collegato:

 It is an error if there is no global var named by the symbol […] 

E:

[…]

  1. Una ricerca viene effettuata nello spazio dei nomi corrente per verificare se esiste una mapping dal simbolo a una var. In tal caso, il valore è il valore dell’associazione della variabile indicata dal simbolo.

  2. È un errore

eval valuta i moduli in un ambiente lessicale vuoto ( null in CL-lingo). Ciò significa che non è ansible accedere ai collegamenti delle variabili lessicali dall’ambito del chiamante. Inoltre, il binding crea nuovi collegamenti per i vars esistenti, motivo per cui non è ansible usarlo “da solo”, senza aver declare o def le variabili che si tenta di associare. Inoltre, le variabili lessicali (almeno in CL, ma sarei sorpreso se questo non fosse il caso di Clojure) sono già cessate di esistere in fase di esecuzione – Vengono tradotte in indirizzi o valori.

Vedi anche il mio post più vecchio su questo argomento.

2 .:

Quindi, devi usare le variabili dinamiche. È ansible evitare la def esplicita, ma è comunque necessario declare (i nomi var def senza binding):

 user=> (declare ^:dynamic x) #'user/x user=> (binding [x 10] (eval '(prn x))) 10 nil 

A proposito: suppongo tu sappia perché hai bisogno di valutazione, e che il suo uso è considerato malvagio quando altre soluzioni sarebbero appropriate.