Tanto defvar
como defparameter
declararán una variable como una "variable de ámbito dinámico". Además, defparameter
siempre establecerá el valor de la variable al valor que pase como segundo argumento. Esto es diferente de defvar
, solo establecerá el valor de la variable si no se ha establecido previamente.
Definir una variable con setf
o setq
en el alcance léxico global no está definido. Algunas implementaciones crearán una variable de ámbito dinámico para usted, otras no. Puede ver mensajes de diagnóstico cuando lo hace por primera vez.
Para entender la diferencia entre las variables léxico de ámbito y dinámicamente con ámbito, pruebe el siguiente fragmento de código:
* (defvar *a* 1)
*A*
* (let ((*a* 5)) (defun demo-a() *a*))
DEMO-A
* (let ((b 5)) (defun demo-b() b))
DEMO-B
* (let ((*a* 100)) (demo-a))
100
* (let ((b 100)) (demo-b))
5
Aquí creamos una variable de forma dinámica con ámbito y una función que devuelve el valor (que se define dentro de una vinculante donde tiene un valor diferente durante la creación de la función, esto no es necesario y se hace solo para parecer similar al cierre léxico sobre b). Luego definimos una nueva variable y definimos una función que devuelve su valor.
Después de eso, llamamos a ambas funciones, dentro de cierres vinculando un valor a una variable del mismo nombre. En el caso del alcance dinámico, es la misma variable. En el caso de cierre léxico (b), simplemente tienen el mismo nombre, pero no son la misma variable, ya que están definidos en dos cierres léxicos diferentes.
En cuanto a la diferencia entre setf
y setq
, trate de usar siempre setf
(no puedo pensar en ningún ejemplo en el que iba a funcionar y (setq blah blahblah)
(setf blah blahblah)
no haría lo mismo).
Si una variable que defino por defvar, ¿puedo cambiar el valor por defparameter? ¿Es la forma correcta de hacerlo? ¿O solo la definición de la variable en el defmámetro puede ser modificada por el defmámetro? Gracias ~ – sam
La forma correcta es usar DEFVAR y DEFPARAMETER para inicializaciones de valor en archivos, use uno u otro para declarar variables dinámicas en el oyente y siempre use SETF para cambiar el valor en código no a nivel. La diferencia entre DEFVAR y DEFPARAMETER se convierte en "¿Quiero restablecer el valor cada vez que cargo este archivo?" (Use defparamete), "¿o no?" (use defvar). – Vatine