What is the difference between "set", "setq", and "setf" in Common Lisp?
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
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))
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.
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.
I would like to add to previous answers that setf is macro that call specific function depending on what was passed as its first argument.
Compare results of macro expansion of setf with different types of arguments:
(macroexpand '(setf a 1))
(macroexpand '(setf (car (list 3 2 1)) 1))
(macroexpand '(setf (aref #(3 2 1) 0) 1))
For some types of arguments "setf function" will be called:
(defstruct strct field)
(macroexpand '(setf (strct-field (make-strct)) 1))
Related
For a program, I'm trying to use a macro such as this one to simplify my code downstream and avoid repeating the same code again and again:
(defmacro destructure (values &body body)
`(let* ((other-values (rest values))
(age (getf other-values :age))
(len (getf other-values :len))
(all (getf other-values :all)))
(progn ,#(loop for e in body collect `(,#e)))))
It is supposed to work with a list such as this:
'(name :age 1 :len 2 :all '(1 2 3 4 5))
The idea is that I should be able to run this code:
(destructure '(name :age 1 :len 2 :all '(1 2 3 4 5))
(type-of age)
(first all))
Or, using a variable, like this:
(setf *values* '(name :age 1 :len 2 :all '(1 2 3 4 5)))
(destructure *values*
(type-of age)
(first all))
Instead of having to access the different elements each time. Of course this is a simplified example, but the list that I have to work on is reality is much longer.
I'm finding it extremely hard to do this. Basically, the code above does not work (unless I cheat by setfing a global variable "values" to hold my list) because the macro is treating the symbol "values" just as that, without expanding the list that it should point to.
On the other hand, I can't use a regular function because then the instructions I'm passing in the body are immediately executed, but I have to place them in the let.
I'm new enough to the language and I believe that I'm probably missing something, and that there probably is a way to achieve it. Is there?
First of all, for your problem you can use destructuring-bind:
(destructuring-bind (name &key age len all)
'(name :age 1 :len 2 :all (1 2 3 4 5))
(list (type-of age)
(type-of len)
(type-of name)
(first all)))
⇒ (BIT (INTEGER 0 4611686018427387903) SYMBOL 1)
Now, some notes about your code:
You have put the reference to values inside a backquote, so it is not a reference to the macro argument, but instead a free reference of the expanded form to some outside variable named values. What you probably meant to do:
(defmacro destructure (values &body body)
`(let* ((other-values ,(rest values)))
(age (getf other-values :age))
(len (getf other-values :len))
(all (getf other-values :all)))
…))
This has a problem in that it shadows any variable named other-values from outside the macro call form. You should use gensyms to avoid that:
(defmacro destructure (values &body body)
(let ((other-values (gensym "other-values")))
`(let* ((,other-values ,(rest values)))
(age (getf other-values :age))
(len (getf other-values :len))
(all (getf other-values :all)))
…))
A note about your code template:
(progn ,#(loop for e in body collect `(,#e))
simplifies to
(progn ,#(loop for e in body collect e))
simplifies to
(progn ,#body)
and since the body of a let already is an implicit progn:
,#body
Finally, your example data:
(name :age 1 :len 2 :all '(1 2 3 4 5))
is actually:
(name :age 1 :len 2 :all (quote (1 2 3 4 5)))
The reader always expands ' to a quote form. When you nest quote forms, you are almost always doing something wrong.
You need to evaluate the values variable in the macro:
? (defmacro destructure (values &body body)
`(let* ((other-values (rest ,values))
(age (getf other-values :age))
(len (getf other-values :len))
(all (getf other-values :all)))
(progn ,#body)))
DESTRUCTURE
? (destructure '(name :age 1 :len 2 :all '(1 2 3 4 5))
(print (type-of age))
(print (first all)))
;Compiler warnings :
; In an anonymous lambda form at position 0: Unused lexical variable LEN
BIT
QUOTE
QUOTE
The QUOTE in the data is not what you want. Quoted data does not need internal quotes.
? (destructure '(name :age 1 :len 2 :all (1 2 3 4 5))
(print (type-of age))
(print (first all)))
;Compiler warnings :
; In an anonymous lambda form at position 0: Unused lexical variable LEN
BIT
1
1
It also works with a variable:
? (let ((values '(name :age 1 :len 2 :all (1 2 3 4 5))))
(destructure values
(print (type-of age))
(print (first all))))
;Compiler warnings :
; In an anonymous lambda form at position 59: Unused lexical variable LEN
BIT
1
1
?
You can also declare the three variables as ignorable. This will silence the warnings above.
What to fix?
The variable other-values is visible in the body.
Let us suppose we have a function func1 :
(defun func1 (&rest values)
; (do something with values...)
(loop for i in values collect i))
Now, we have a function func2 which calls func1 :
(defun func2 (&rest values)
; (do something with values...)
(func1 ???))
What should I put instead of ??? to "copy" all the parameters of func2's values to func1's values ?
For instance, I would have the following behavior :
(func2 1 2 3 4) ; result is (1 2 3 4) and not ((1 2 3 4)).
In an earlier question I tried to do something like this :
(defun func2 (&rest values)
(macrolet ((my-macro (v)
`(list ,#v)))
(func1 (my-macro values))))
But the defun cannot get the value because it is not runtime. In this answer, he suggested that I use apply, but this function takes a &rest parameter too, so it doesn't solve my problem...
If possible, I would rather avoid to change the prototype of both functions, and the behavior of func1.
In common lisp, it has to be
(apply #'func1 values) ;; since `func1` has to be looked up in function namespace
remember, Clojure and Racket/Scheme are Lisp1, and common lisp is Lisp2.
Alternative solution (just for the sake)
I was asking myself, how to get it done without apply - just for the sake.
The problem with
`(func2 ,#values)
is, that if e.g.
(func2 (list 1 2 3) (list 4) 5)
is called, the values variable is ((1 2 3) (4) 5)
But when it is spliced into (func1 ,#values), what is created is
(func1 (1 2 3) (4) 5). But if we compare this with the func2 call,
it should be rather (func1 (list 1 2 3) (list 4) 5) which is perhaps not possible, because when (func2 (list 1 2 3) (list 4) 5) is called -
in the lisp manner - the arguments of func2 are each evaluated, before they enter the function body of func2, so we end up with values as a list of already evaluated arguments, namely ((1 2 3) (4) 5).
So somehow, concerning the arguments for func1 in the last expression, we are one evaluation-step offbeat.
But there is a solution with quote, that we manage to quote each of the arguments before giving it to func1 in the last expression, to "synchronize" the func1 function call - to let the arguments' evaluation pause for one round.
So my first aim was to generate a new values list inside the func2 body where each of the values list's argument is quoted (this is done in the let-binding).
And then at the end to splice this quoted-values list into the last expression: (func1 '(1 2 3) '(4) '5) which can be regarded as equivalent to (func1 (list 1 2 3) (list 4) 5) for this kind of problems / for this kind of calls.
This was achieved by this code:
(defun func2 (&rest vals)
(let ((quoted-values (loop for x in vals
collect `',x)))
; do sth with vals here - the func2 function -
(eval `(func1 ,#quoted-values))))
This is kind of a macro (it creates code btw. it organizes new code) but executed and created in run-time - not in pre-compile time. Using an eval we execute that generated code on the fly.
And like macroexpand-1, we can look at the result - the code - to which the func1 expression "expands", by removing eval around it - I call it func2-1:
(defun func2-1 (&rest vals)
(let ((quoted-values (loop for x in vals
collect `',x)))
; do sth with vals here - the func2 function -
`(func1 ,#quoted-values)))
And if we run it, it returns the last expression as code immediately before it is evluated in the func2 version:
(func2-1 (list 1 2 3) (list 4) 5)
;; (FUNC1 '(1 2 3) '(4) '5) ;; the returned code
;; the quoted arguments - like desired!
And this happens if we call it using func2 (so with evaluation of the func1 all:
(func2 (list 1 2 3) (list 4) 5)
;; ((1 2 3) (4) 5) ;; the result of (FUNC1 '(1 2 3) '(4) '5)
So I would say this is exactly what you desired!
lists vs. spread arguments
In Common Lisp it is good style to pass lists as lists and not as spread arguments:
(foo (list 1 2 3)) ; better interface
(foo 1 2 3) ; interface is not so good
The language has been defined in a way that efficient function calling can be used by a compiler and this means that the number of arguments which can be passed to a function is limited. There is a standard variable which will tell us how many arguments a particular implementation supports:
This is LispWorks on my Mac:
CL-USER 13 > call-arguments-limit
2047
Some implementations allow much larger number of arguments. But this number can be as low as 50 - for example ABCL, Common Lisp on the JVM, allows only 50 arguments.
Computing with argument lists
But sometimes we want the arguments as a list and then we can use the &rest parameter:
(lambda (&rest args)
(print args))
This is slightly in-efficient, since a list will be consed for the arguments. Usually Lisp tries to avoid to cons lists for arguments - they will be passed in registers or on the stack - if possible.
If we know that the argument list will not be used, then we can give the compiler a hint to use stack allocation - if possible:
(lambda (&rest args)
(declare (dynamic-extent args))
(reduce #'+ args))
In above function, the list of arguments can be deallocated when leaving the function - because the argument list is no longer used then.
If you want to pass these arguments to another function you can use FUNCALL and usually more useful APPLY:
(lambda (&rest args)
(funcall #'write (first args) (second args) (third args)))
or more useful:
(lambda (&rest args)
(apply #'write args))
One can also add additional arguments to APPLY before the list to apply:
CL-USER 19 > ((lambda (&rest args)
(apply #'write
(first args) ; the object
:case :downcase ; additional args
(rest args))
(values))
'(defun foo () 'bar)
:pretty t
:right-margin 15)
(defun foo ()
'bar)
I feel as though I'm in the same ballpark as Basic Lisp Macro error
but when I imagine how the code should look when expanded I don't see a problem and macroexpand isn't helping because it just doesn't want to output anything I can print; macroexpand just runs the code for me.
(setf my-array (make-array 4 :initial-element 3))
(print my-array)
(setf (aref my-array 2) 5)
(print my-array)
(defmacro set3To5 (arrnum)
(print (arrayp arrnum))
(print arrnum)
(setf (aref arrnum 3) 5)
)
(set3To5 my-array)
Running this gives me the output
argument MY-ARRAY is not an array
but if 'arrnum' is replaced by 'my-array' then it should be fine?
To quote from the linked question
Now on macro expansion, the macro ADD-TEST is called with the parameter VAR getting the value G, a symbol.
Certainly my-array is a symbol and it is the symbol I wish to manipulate so why is there a problem?
Let’s write down what would happen if a lisp were to evaluate your file line by line:
(setf my-array (make-array 4 :initial-element 3))
At this point we have MY-ARRAY bound to #(3 3 3 3)
(print my-array)
Prints #(3 3 3 3)
(setf (aref my-array 2) 5)
(print my-array)
Modifies an element and prints #(3 3 5 3)
(defmacro set3To5 (arrnum)
(print (arrayp arrnum))
(print arrnum)
(setf (aref arrnum 3) 5))
Now the macro SET3TO5 has been defined.
(set3To5 my-array)
The first step here (which we haven’t mentioned before, even though it was happening) is macroexpansion. The compiler knows that SET3TO5 is a macro so it calls the macro function with MY-ARRAY (the symbol) as arguments. Let’s look at what happens inside that macro:
(print (arrayp arrnum))
Well ARRNUM is the symbol MY-ARRAY so this prints NIL, although possibly not to the stream you expect.
(print arrnum)
This prints MY-ARRAY.
(setf (aref arrnum 3) 5)
Well ARRNUM is not an array so you have an error here.
So we have failed to evaluate this expression because expanding the macro has failed.
Here are some other things you could do:
(defun set1 (arrnum)
(print (arrayp arrnum))
(print arrnum)
(setf (aref arrnum 3) 5))
(defun set2 (arrnum)
(list 'setf (list 'aref arrnum 3) 5))
(defmacro set3 (arrnum)
(list 'setf (list 'aref arrnum 3) 5))
And now evaluate:
CL-USER> (set1 my-array)
T
#(3 3 5 3)
5
CL-USER> my-array
#(3 3 5 5)
CL-USER> (set2 my-array)
(SETF (AREF #(3 3 5 5) 3) 5)
CL-USER> (set2 'foo)
(SETF (AREF FOO 3) 5)
CL-USER> (setf (aref my-array 3) 1)
1
CL-USER> (set3 my-array)
5
CL-USER> my-array
#(3 3 5 5)
Long story short, the code should look like this to leave you with an array of (3 3 5 5).
(defmacro set3To5 (arrnum)
`(print (type-of ,arrnum))
`(setf (aref ,arrnum 3) 5)
)
GNU Common Lisp, at least, cares a lot about the difference between ` and ' (those are backtick/backquote and quote/apostrophe characters). What does backtick mean in LISP?
The comma operator undoes the quotation for an element in the list, allowing you to plug in parameters or local variables, do ",#" for splicing in a list.
Lisp macros execute the code within their bodies and the return result should be a form that can then be executed, that is macro expansion.
It seems to be they just decided on magic to define how the two backquoted lines are both turned into code because it seems like you would have to put them both within a list and backquote the entire list and then return that list, but it does look neater this way.
I am trying to format an arbitrary expression, say (+ 2 3), and at the same time, its result, 5.
I have the following:
(defun expr-and-result (expr)
(format t "~a returns ~a~%" expr (eval expr)))
CL-USER> (expr-and-result '(+ 2 3))
(+ 2 3) returns 5
Though it's a simple matter by using eval, I'm curious if this effect can be accomplished without it (because I heard a lot that eval is to be avoided).
I understand that quoting the argument is necessary, because otherwise the given expression will be evaluated as the first step in calling expr-and-result, and only its result could be used inside expr-and-result. Therefore, any possible solution requires the input to be quoted, right?
I thought a bit about macros but I feel like it's the wrong approach to what I am looking for.
Edit: My intent was to construct a simple test-suite, such as:
(progn
(mapcar #'expr-and-result
'((= (my-remainder 7 3) 1)
(= (my-remainder 7 3) 2)))
'end-of-tests)
Outputs:
(= (MY-REMAINDER 7 3) 1) returns T
(= (MY-REMAINDER 7 3) 2) returns NIL
END-OF-TESTS
After reading Paulo's comment, it seems that eval is the shortest and cleanest solution for my purposes.
Here is a simple macro:
(defmacro exec-and-report (form)
`(format t "~S returns ~S~%" ',form ,form))
(macroexpand '(exec-and-report (+ 1 2)))
==>
(FORMAT T "~S returns ~S~%" '(+ 1 2) (+ 1 2)) ;
T
(exec-and-report (+ 1 2))
==>
(+ 1 2) returns 3
NIL
PS. I second #Sylvester's suggestion not to reinvent the wheel
I think I just use setq (or setf, I'm not really sure the difference), but I don't understand how to reference the [i][j]-th element in an array in lisp.
My start condition is this:
? (setq x (make-array '(3 3)))
#2A((0 0 0) (0 0 0) (0 0 0))
I want to alter, say, the 2nd item of the 3rd "row" to give this:
? ;;; What Lisp code goes here?!
#2A((0 0 0) (0 0 0) (0 "blue" 0))
The following, which I would have thought close, gives an error:
(setq (nth 1 (nth 2 x)) "blue")
So what's the correct syntax?
Thanks!
I think proper way is to use setf with aref like this:
(setf (aref x 2 1) "blue")
For more details see reference.
You can find a dictionary of the ARRAY operations in the Common Lisp HyperSpec (the web version of the ANSI Common Lisp standard:
http://www.lispworks.com/documentation/lw50/CLHS/Body/c_arrays.htm
AREF and (SETF AREF) are documented here:
http://www.lispworks.com/documentation/lw50/CLHS/Body/f_aref.htm
The syntax to set an array element is: (setf (aref array &rest subscripts) new-element).
Basically if you want to set something in Common Lisp, you just need to know how to get it:
(aref my-array 4 5 2) ; access the contents of an array at 4,5,2.
Then the set operation is schematically:
(setf <accessor code> new-content)
This means here:
(setf (aref my-array 4 5 2) 'foobar) ; set the content of the array at 4,5,2 to
; the symbol FOOBAR
The correct invocation is
(setf (aref x 2 1) "blue")
setq is used when you're assigning to a variable. Only setf knows how to "reach into" compound objects as with setting a value in your array. Of course, setf also knows how to assign to variables, so if you stick with setf you'll always be okay.