52

I found a Similar question.

But I don't quite understand that explanation.

So I'm trying to run clisp with the following example:

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

What I found is totally the same.

I can't figure out what's different with them?

Community
  • 1
  • 1
sam
  • 2,049
  • 3
  • 20
  • 27

2 Answers2

80

DEFPARAMETER always assigns a value. So:

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

while DEFVAR does it only once, so:

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

SETF is a macro which uses SETQ internally, but has more possibilities. In a way it's a more general assignment operator. E.g. with SETF you can do:

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

but you can't do that with 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
Steffo
  • 305
  • 5
  • 13
Michał Kwiatkowski
  • 9,196
  • 2
  • 25
  • 20
  • If a variable which I define by defvar,can I change value by defparameter? Is the the correct way to do it? Or only the variable define in defparameter can be changed by defparameter? Thank you~ – sam Jan 19 '12 at 15:03
  • 38
    The right way is to use DEFVAR and DEFPARAMETER for value initializations in files, use one or the other to declare dynamic variables in the listener and always use SETF to change the value in non-toplevel code. The difference between DEFVAR and DEFPARAMETER then becomes "do I want to reset the value every time I load this file," (use defparamete), "or not?" (use defvar). – Vatine Jan 19 '12 at 15:17
31

Both defvar and defparameter will declare a variable as a "dynamically scoped variable". In addition, defparameter will always set the value of the variable to the value you pass in as the second argument. This is different from defvar, it will only set the value of the variable if it previously hasn't been set.

Defining a variable with setf or setq in the global lexical scope is undefined. Some implementations will create a dynamically scoped variable for you, some will not. You may see diagnostic messages when you do it for the first time.

To understand the difference between lexically-scoped and dynamically-scoped variables, try the following code snippet:

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

Here we create a dynamically-scoped variable and a function that return the value (defined inside a binding where it has a different value during the function creation, this is not necessary and done only to look similar to the lexical closure over b). We then define a new variable and define a function return its value.

After that, we call both functions, inside closures binding a value to a variable of the same name. In the dynamic scoping case, it is the same variable. In the lexical closure case (b), they merely have the same name, but are not the same variable, since they're defined in two different lexical closures.

As far as the difference between setf and setq, try to always use setf (I cannot think of any example where (setq blah blahblah) would work and (setf blah blahblah) wouldn't do the same thing).

Vatine
  • 20,782
  • 4
  • 54
  • 70
  • Now I know the difference between defvar and defparameter. But when is the case we should use setf or setq? Thank you~ – sam Jan 19 '12 at 15:01
  • 8
    @sam: use `defvar`, `defparameter`, or `let` to introduce new variables. Use `setf` and `setq` to mutate existing variables. Using them to introduce new variables is undefined behaviour. – Rörd Jan 19 '12 at 19:29
  • Last example (let ((b 100)) (demo-b)) gives me 100 also, not 5 as shown – Andreas Röhler Oct 12 '13 at 16:16
  • 1
    @AndreasRöhler If it does you may have done a toplevel `(setq b...)` earlier, that will cause multiple lisp environments to turn the variable into dynamically-scoped. What happens if you try it in a freshly-started Common Lisp? – Vatine Oct 13 '13 at 09:54
  • @Vatine Ahh, sorry, was at Emacs Lisp dynamically scoped. – Andreas Röhler Oct 18 '13 at 14:51
  • Worth mentioning that `(demo-a)`, without a `let` surrounding its call, evaluates to the `1`. – gypsydave5 Aug 16 '18 at 18:13