lisp - mac - Cuál es la diferencia entre defvar, defparameter, setf y setq
compiladores lisp (2)
DEFPARAMETER siempre asigna un valor. Asi que:
[1]> (defparameter a 1)
A
[2]> (defparameter a 2)
A
[3]> a
2
mientras que DEFVAR lo hace solo una vez, entonces:
[4]> (defvar b 1)
B
[5]> (defvar b 2)
B
[6]> b
1
SETF es una macro que usa SETQ internamente, pero tiene más posibilidades. En cierto modo, es un operador de asignación más general. Por ejemplo, con SETF puedes hacer:
[19]> (defparameter c (list 1 2 3))
[21]> (setf (car c) 42)
42
[22]> c
(42 2 3)
pero no puedes hacer eso con SETQ:
[23]> (setq (car c) 42)
*** - SETQ: (CAR C) is not a symbol
The following restarts are available:
USE-VALUE :R1 Input a value to be used instead.
ABORT :R2 Abort main loop
Break 1 [24]> abort
Encontré una pregunta similar .
Pero no entiendo muy bien esa explicación.
Así que estoy tratando de ejecutar clisp con el siguiente ejemplo:
[1]> (defvar a 5)
A
[2]> (+ a 1)
6
[3]> (defparameter b 5)
B
[4]> (+ b 1)
6
[5]> (setf c 5)
5
[6]> (+ c 1)
6
[7]> (setq d 5)
5
[8]> (+ d 1)
6
[9]> (let ((a 500)) (+ a 1))
501
[10]> (let ((b 500)) (+ b 1))
501
[11]> (let ((c 500)) (+ c 1))
501
[12]> (let ((d 500)) (+ d 1))
501
[13]>
Lo que encontré es totalmente lo mismo.
No puedo entender lo que es diferente con ellos?
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 comprender la diferencia entre las variables de ámbito léxico y de ámbito dinámico, 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 ámbito dinámico y una función que devuelve el valor (definido dentro de un enlace 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 los 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
, intenta usar siempre setf
(no puedo pensar en ningún ejemplo donde (setq blah blahblah)
funcione y (setf blah blahblah)
no haría lo mismo).