Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between `set`, `setq`, and `setf` in Common Lisp?

Tags:

common-lisp

People also ask

What does Setf mean in Common 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 does SETQ mean in Lisp?

(setq var1 form1 var2 form2 ...) is the simple variable assignment statement of Lisp. First form1 is evaluated and the result is stored in the variable var1, then form2 is evaluated and the result stored in var2, and so forth. setq may be used for assignment of both lexical and dynamic variables.

What does SETQ mean?

(The ' q ' in setq means quote .) With set , the expression would look like this: (set 'carnivores '(lion tiger leopard)) Also, setq can be used to assign different values to different variables.

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


Originally, in Lisp, there were no lexical variables -- only dynamic ones. And there was no SETQ or SETF, just the SET function.

What is now written as:

(setf (symbol-value '*foo*) 42)

was written as:

(set (quote *foo*) 42)

which was eventually abbreviavated to SETQ (SET Quoted):

(setq *foo* 42)

Then lexical variables happened, and SETQ came to be used for assignment to them too -- so it was no longer a simple wrapper around SET.

Later, someone invented SETF (SET Field) as a generic way of assigning values to data structures, to mirror the l-values of other languages:

x.car := 42;

would be written as

(setf (car x) 42)

For symmetry and generality, SETF also provided the functionality of SETQ. At this point it would have been correct to say that SETQ was a Low-level primitive, and SETF a high-level operation.

Then symbol macros happened. So that symbol macros could work transparently, it was realized that SETQ would have to act like SETF if the "variable" being assigned to was really a symbol macro:

(defvar *hidden* (cons 42 42))
(define-symbol-macro foo (car *hidden*))

foo => 42

(setq foo 13)

foo => 13

*hidden* => (13 . 42)

So we arrive in the present day: SET and SETQ are atrophied remains of older dialects, and will probably be booted from eventual successors of Common Lisp.


(set ls '(1 2 3 4)) => Error - ls has no value

(set 'ls '(1 2 3 4)) => OK

(setq ls '(1 2 3 4)) => OK - make ls to (quote ls) and then have the usual set

(setf ls '(1 2 3 4)) => OK - same as setq so far BUT

(setf (car ls) 10) => Makes ls '(10 2 3 4) - not duplicated by setq/set

setq is just like set with a quoted first arg -- (set 'foo '(bar baz)) is just like (setq foo '(bar baz)). setf, on the other hand, is subtle indeed -- it's like an "indirection". I suggest http://www.n-a-n-o.com/lisp/cmucl-tutorials/LISP-tutorial-16.html as a better way to get started understanding it than any answer here can give... in short, though, setf takes the first argument as a "reference", so that e.g. (aref myarray 3) will work (as the first arg to setf) to set an item inside an array.


You can use setf in place of set or setq but not vice versa since setf can also set the value of individual elements of a variable if the variable has individual elements. See the exaples below:

All four examples will assign the list (1, 2, 3) to the variable named foo.

(set (quote foo) (list 1 2 3))    ;foo => (1 2 3)
(1 2 3)

(set 'foo '(1 2 3))   ;foo => (1 2 3) same function, simpler expression
(1 2 3)

(setq foo '(1 2 3))   ;foo => (1 2 3) similar function, different syntax
(1 2 3)

(setf foo '(1 2 3))   ;foo => (1 2 3) more capable function
(1 2 3)

setf has the added capability of setting a member of the list in foo to a new value.

foo                   ;foo => (1 2 3) as defined above
(1 2 3)

(car foo)             ;the first item in foo is 1
1

(setf (car foo) 4)    ;set or setq will fail since (car foo) is not a symbol
4

foo                   ;the fist item in foo was set to 4 by setf
(4 2 3)

However, you can define a symbol macro that reprents a single item within foo

(define-symbol-macro foo-car (car foo))    ; assumes FOO => (1 2 3)
FOO-CAR

foo-car               ;foo-car is now a symbol for the 1st item in foo
1

(setq foo-car 4)      ;set or setq can set the symbol foo-car 
4

foo                   ;Lisp macros are so cool
(4 2 3)

You can use defvar if you have not already defined the variable and do not want to give it a value until later in your code.

(defvar foo2)
(define-symbol-macro foo-car (car foo2))

One can think of SET and SETQ being low-level constructs.

  • SET can set the value of symbols.

  • SETQ can set the value of variables.

Then SETF is a macro, which provides many kinds of setting things: symbols, variables, array elements, instance slots, ...

For symbols and variables one can think as if SETF expands into SET and SETQ.

* (macroexpand '(setf (symbol-value 'a) 10))

(SET 'A 10)


* (macroexpand '(setf a 10))         

(SETQ A 10)

So SET and SETQ are used to implement some of the functionality of SETF, which is the more general construct. Some of the other answers tell you the slightly more complex story, when we take symbol macros into account.