Quelle est la différence entre defvar, defparameter, setf et setq?

j'ai trouvé un question similaire .

mais je ne comprends pas bien cette explication.

donc j'essaie d'exécuter clisp avec l'exemple suivant:

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

ce que j'ai trouvé est totalement le même.

Je n'arrive pas à comprendre ce qui est différent avec eux?

35
demandé sur Community 2012-01-19 18:28:30

2 réponses

DEFPARAMETER attribue toujours une valeur. So:

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

alors que DEFVAR ne le fait qu'une seule fois, donc:

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

SETF est une macro qui utilise SETQ en interne, mais qui offre plus de possibilités. D'une certaine façon, c'est un opérateur de mission plus général. Par exemple: avec SETF vous pouvez faire:

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

mais vous ne pouvez pas faire ça avec 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
60
répondu Michał Kwiatkowski 2016-07-28 17:09:06

les deux defvar et defparameter déclareront une variable comme une"variable à portée dynamique". De plus, defparameter définira toujours la valeur de la variable à la valeur dans laquelle vous passez comme second argument. C'est différent de defvar , il ne définira la valeur de la variable que si elle n'a pas été définie auparavant.

définir une variable avec setf ou setq dans la portée lexicale globale n'est pas défini. Certaines implémentations créez une variable à portée dynamique pour vous, certains ne le feront pas. Vous pouvez voir les messages de diagnostic lorsque vous le faites pour la première fois.

pour comprendre la différence entre les variables à portée lexique et à portée dynamique, essayez l'extrait de code suivant:

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

ici, nous créons une variable à portée dynamique et une fonction qui renvoie la valeur (définie à l'intérieur d'une liaison où elle a une valeur différente lors de la création de la fonction, c'est pas nécessaire et fait seulement pour ressembler à la fermeture lexicale sur b). Nous définissons alors une nouvelle variable et définissons une fonction renvoie sa valeur.

après cela, nous appelons les deux fonctions, à l'intérieur des fermetures liant une valeur à une variable du même nom. Dans le cas de la détermination dynamique de la portée, il s'agit de la même variable. Dans le cas de la fermeture lexicale (b), ils ont simplement le même nom, mais ne sont pas la même variable, puisqu'ils sont définis dans deux fermetures lexicales différentes.

en ce qui concerne la différence entre setf et setq , essayez toujours d'utiliser setf (Je ne vois pas d'exemple où (setq blah blahblah) fonctionnerait et (setf blah blahblah) ne ferait pas la même chose).

23
répondu Vatine 2016-07-28 08:50:29