Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's difference between defvar, defparameter, setf and setq

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?

like image 373
sam Avatar asked Jan 19 '12 14:01

sam


People also ask

What is Defparameter in Common Lisp?

DEFPARAMETER defines global variable with dynamic scoping. Usual conventions dictate to make such variables easy to distinguish so their name is surrounded by stars. Value for variable is reevaluated for each occurence (unlike with DEFVAR).

What is Setf in Lisp?

setf is actually a macro that examines an access form and produces a call to the corresponding update function. Given the existence of setf in Common Lisp, it is not necessary to have setq, rplaca, and set; they are redundant. They are retained in Common Lisp because of their historical importance in Lisp.

What is Defvar Lisp?

In Emacs Lisp, a variable such as the kill-ring is created and given an initial value by using the defvar special form. The name comes from “define variable”. The defvar special form is similar to setq in that it sets the value of a variable.


2 Answers

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 
like image 194
Michał Kwiatkowski Avatar answered Oct 12 '22 07:10

Michał Kwiatkowski


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

like image 29
Vatine Avatar answered Oct 12 '22 07:10

Vatine