2012-01-19 9 views
31

Ho trovato un Similar question.Qual è la differenza tra defvar, defparameter, setf e setq

Ma non capisco questa spiegazione.

Così sto cercando di eseguire clisp con il seguente esempio:

[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]> 

Quello che ho trovato è totalmente lo stesso.

Non riesco a capire cosa c'è di diverso con loro?

risposta

55

DEFPARAMETER assegna sempre un valore. Quindi:

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

mentre defvar lo fa solo una volta, in modo da:

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

SETF è una macro che utilizza setq internamente, ma ha più possibilità. In un certo senso è un operatore di assegnazione più generale. Per esempio. con SETF si può fare:

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

ma non è possibile farlo 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

Se una variabile che definisco con defvar, posso modificare il valore con defparameter? È il modo corretto per farlo? O solo la variabile definita in defparameter può essere modificata da defparameter? Grazie ~ – sam

+22

Il modo corretto è utilizzare DEFVAR e DEFPARAMETER per l'inizializzazione dei valori nei file, utilizzare l'uno o l'altro per dichiarare le variabili dinamiche nel listener e utilizzare sempre SETF per modificare il valore nel codice non di primo livello. La differenza tra DEFVAR e DEFPARAMETER diventa quindi "Voglio reimpostare il valore ogni volta che carico questo file" (usa defparamete), "oppure no?" (usa defvar). – Vatine

22

Entrambe defvar e defparameter dichiareranno una variabile come "variabile ad ambito dinamico". Inoltre, defparameter imposterà sempre il valore della variabile sul valore inserito come secondo argomento. Questo è diverso da defvar, imposterà solo il valore della variabile se precedentemente non è stato impostato.

La definizione di una variabile con setf o setq nello scope lessicale globale non è definita. Alcune implementazioni creeranno per te una variabile con ambito dinamico, altre no. Potresti visualizzare messaggi diagnostici quando lo fai per la prima volta.

per capire la differenza tra le variabili lessicalmente con ambito e dinamicamente con ambito, provare il seguente frammento di codice:

* (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 

Qui creiamo una variabile in modo dinamico con ambito e una funzione che restituisce il valore (definito all'interno di un vincolante dove ha un valore diverso durante la creazione della funzione, questo non è necessario e fatto solo per sembrare simile alla chiusura lessicale su b). Quindi definiamo una nuova variabile e definiamo una funzione restituisce il suo valore.

Successivamente, chiamiamo entrambe le funzioni, all'interno di chiusure che vincolano un valore a una variabile con lo stesso nome. Nel caso di ambito dinamico, è la stessa variabile. Nel caso lessicale di chiusura (b), hanno semplicemente lo stesso nome, ma non sono la stessa variabile, poiché sono definiti in due diverse chiusure lessicali.

Per quanto riguarda la differenza tra setf e setq, cerca di utilizzare sempre setf (non riesco a pensare a nessun esempio in cui (setq blah blahblah) avrebbe funzionato e (setf blah blahblah) non farei la stessa cosa).

+0

Ora so la differenza tra defvar e defparameter. Ma quando è il caso dovremmo usare setf o setq? Grazie ~ – sam

+6

@sam: usa 'defvar',' defparameter' o 'let' per introdurre nuove variabili. Usa 'setf' e' setq' per mutare le variabili esistenti.Usarli per introdurre nuove variabili è un comportamento indefinito. –

+0

L'ultimo esempio (let ((b 100)) (demo-b)) mi dà anche 100, non 5 come mostrato –

Problemi correlati