Basta associare una variabile con una copia del valore. Ad esempio:
(let ((i i))
(lambda() i))
Questo è in realtà una tecnica importante con costrutti di iterazione, perché qualcosa di simile
(loop for i from 1 to 10
collecting (lambda() i))
può restituire dieci chiusure sopra le stesse variabili, per cui diventa necessario scrivere:
(loop for i from 1 to 10
collecting (let ((i i)) (lambda() i)))
Se in realtà serve solo una funzione che restituisce il valore, è possibile utilizzare anche constantly (ma mi aspetto che il caso di utilizzo reale sia più complicato):
(loop for i from 1 to 10
collecting (constantly i))
L'ambiguità nei moduli di iterazione è in realtà specificata dallo standard, in alcuni casi. Ad esempio, per dotimes, dolist
Si è dipendente sia dotimes stabilisce una nuova associazione di var ad ogni iterazione o se stabilisce un attacco per var volta all'inizio e poi assegna su eventuali iterazioni successive.
Più primitivo do, tuttavia, specifica realtà che v'è una serie di attacchi per la forma, e che vengono aggiornati ad ogni iterazione (corsivo):
All'inizio di ogni iterazione diversa dalla prima, vars sono aggiornate come segue.& Hellip;
Questa ambiguità conferisce maggiore flessibilità alle implementazioni. DOLIST, per esempio potrebbe essere definita con una delle seguenti operazioni:
(defmacro dolist ((var list &optional result) &body body)
`(progn (mapcar #'(lambda (,var)
,@(ex:body-declarations body)
(tagbody
,@(ex:body-tags-and-statements body)))
,list)
(let ((,var nil))
,result)))
(defmacro dolist ((var list &optional result) &body body)
(let ((l (gensym (string '#:list-))))
`(do* ((,l ,list (rest ,l))
(,var (first ,l) (first ,l)))
((endp ,l) ,result)
,@body)))
I propongo di leggere un po 'di 'LET'. –