2012-01-19 17 views
31

Encontré un Similar question.Cuál es la diferencia entre defvar, defparameter, setf y setq

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 igual.

No puedo entender lo que es diferente con ellos?

Respuesta

55

DEFPARAMETER siempre asigna un valor. Por lo tanto:

[1]> (defparameter a 1) 
A 
[2]> (defparameter a 2) 
A 
[3]> a 
2 

mientras defvar lo hace sólo una vez, por lo que:

[4]> (defvar b 1) 
B 
[5]> (defvar b 2) 
B 
[6]> b 
1 

SETF es una macro que utiliza internamente setq, pero tiene más posibilidades. En cierto modo, es un operador de asignación más general. P.ej. con SETF que puede hacer:

[19]> (defparameter c (list 1 2 3)) 
[21]> (setf (car c) 42)            
42 
[22]> c 
(42 2 3) 

pero no se puede 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 
+0

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

+22

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

22

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).

+0

Ahora sé la diferencia entre defvar y defparameter. Pero cuando es el caso, ¿deberíamos usar setf o setq? Gracias ~ – sam

+6

@sam: use 'defvar',' defparameter', o 'let' para introducir nuevas variables. Use 'setf' y' setq' para mutar las variables existentes.Usarlos para introducir nuevas variables es un comportamiento indefinido. –

+0

Último ejemplo (let ((b 100)) (demo-b)) me da 100 también, no 5 como se muestra –

Cuestiones relacionadas