Solución:
setq
asigna un valor a una variable, mientras que let
introduce nuevas variables / enlaces. Por ejemplo, mira lo que pasa en
(let ((x 3))
(print x) ; a
(let ((x 89))
(print x) ; b
(setq x 73)
(print x)) ; c
(print x)) ; d
3 ; a
89 ; b
73 ; c
3 ; d
El exterior let
crea una variable local x
y el interior let
crea otra variable local que sombrea la interior. Tenga en cuenta que el uso de let
sombrear la variable no afecta el valor de la variable sombreada; los x
en línea d
es el x
introducido por el exterior let
y su valor no ha cambiado. setq
solo afecta a la variable con la que se llama. Este ejemplo muestra setq
se usa con variables locales, pero también puede ser con variables especiales (es decir, con alcance dinámico y generalmente definido con defparameter
o defvar
:
CL-USER> (defparameter *foo* 34)
*FOO*
CL-USER> (setq *foo* 93)
93
CL-USER> *foo*
93
Tenga en cuenta que setq
does (portátil) crear variables, mientras que let
, defvar
, defparameter
, &C. hacer. El comportamiento de setq
cuando se llama con un argumento que no es una variable (todavía) no está definido, y depende de una implementación decidir qué hacer. Por ejemplo, SBCL se queja en voz alta:
CL-USER> (setq new-x 89)
; in: SETQ NEW-X
; (SETQ NEW-X 89)
;
; caught WARNING:
; undefined variable: NEW-X
;
; compilation unit finished
; Undefined variable:
; NEW-X
; caught 1 WARNING condition
89
Por supuesto, la mejor manera de obtener una mejor comprensión de estos conceptos es leer y escribir más código Lisp (que viene con el tiempo) y leer las entradas en HyperSpec y seguir las referencias cruzadas, especialmente las entradas del glosario. Por ejemplo, las descripciones breves de HyperSpec para setq
y let
incluir:
-
SETQ
Asigna valores a variables.
-
LET
deja y deja * crear una nueva variable fijaciones y ejecutar una serie de formularios que utilizan estos enlaces.
Es posible que desee leer más sobre variables y enlaces. let
y let*
también tienen un comportamiento especial con variables dinámicas y special
declaraciones (pero probablemente no necesitará saber sobre eso por un tiempo), y en ciertos casos (que probablemente no necesitará conocer por un tiempo) cuando una variable no es realmente una variable, setq
es en realidad equivalente a setf
. HyperSpec tiene más detalles.
Hay algunas preguntas no del todo duplicadas en Stack Overflow que, no obstante, pueden ayudar a comprender el uso de los diversos operadores de asignación y definición de variables disponibles en Common Lisp:
- setq y defvar en lisp
- ¿Cuál es la diferencia entre defvar, defparameter, setf y setq?
- Asignar variables con setf, defvar, let y scope
- En Lisp, ¿cómo soluciono “Advertencia: Supuestamente especial?” (re: usando
setq
en variables indefinidas) - ¿Diferencia entre let * y set? en Common Lisp
Casi siempre debería ser la forma en que enlaza variables dentro de una definición de función, excepto en el raro caso en el que desea que el valor esté disponible para otras funciones en el mismo ámbito.
Me gusta la descripción en el manual de emacs lisp:
let se usa para adjuntar o vincular un símbolo a un valor de tal manera que el intérprete Lisp no confunda la variable con una variable del mismo nombre que no es parte de la función.
Para comprender por qué es necesaria la forma especial de alquiler, considere la situación en la que es propietario de una casa a la que generalmente se refiere como “la casa”, como en la oración “La casa necesita pintura”. Si está visitando a un amigo y su anfitrión se refiere a “la casa”, es probable que se refiera a su casa, no a la suya, es decir, a una casa diferente.
Si su amigo se refiere a su casa y usted cree que se refiere a su casa, es posible que se sienta confuso. Lo mismo podría suceder en Lisp si una variable que se usa dentro de una función tiene el mismo nombre que una variable que se usa dentro de otra función, y no se pretende que las dos se refieran al mismo valor. La forma especial let evita este tipo de confusión.
– http://www.gnu.org/software/emacs/manual/html_node/eintr/let.html