push does not work as I would expect it - why?
common-lisp, lisp
Solution
If you read the CL Hyperspec for PUSH, you will read that `push` expects a place.
A place is something like a variable, a structure slot, a class slot, an array access, or similar. Since Lisp uses linked cons cells for lists, it does not make sense to push something in front of a cons cell, without a reference for that.
So above is simple: we can't push to a direct list.
Why this error message?
This gets a bit complicated...
(push 2 '(3 5 7 11))
Is actually:
(push 2 (quote (3 5 7 11))
A function can be a place, it then needs a corresponding setter function. Here the setter is thought to be `(setf quote)` - that's right, Common Lisp can sometimes have lists as function names, not only symbols.
If we look at the macroexpansion of above:
? (pprint (macroexpand '(push 2 (quote (3 5 7 11)))))
(LET* ((#:G328 2) (#:G327 (3 5 7 11)) (#:G326 (CONS #:G328 '#:G327)))
#:G327
#:G326
(FUNCALL #'(SETF QUOTE) #:G326 #:G327))
You can see that it tries to call the setter. But it also thinks that `(3 5 7 11)` is a Lisp form.
I give you an example, where it actually works, but we don't use `quote`, but a real accessor function:
CL-USER 40 > (let ((v (vector (list (list 'a 'b 'c) (list 'd 'e 'f))
(list (list 1 2 3) (list 4 5 6)))))
(print v)
(push 42 (first (aref v 1)))
(print v)
(values))
#(((A B C) (D E F)) ((1 2 3) (4 5 6)))
#(((A B C) (D E F)) ((42 1 2 3) (4 5 6)))
In above `first` is the getter and CL knows the corresponding setter. The form `(aref v 1)` is the call and returns the index 1 element of the vector. We are then pushing to the first list of the element.
Your call has a similar structure and `(3 5 7 11)` is at a similar position as `(aref v 1)`. The Lisp system says that in `(3 4 7 11)` then number `3` is not a valid function. Which is correct. But the real error was about the `push` operation. Since the macro could not detect the error, the error gets later detected in the macro expanded code.
Problem
I am experiencing a behavior of the `push` function that I don't get. Maybe someone could explain to me why Lisp behaves this way. Supposed I define a list as a global variable, and then try to push a new value to it using the following code: ``` (defparameter *primes* '(3 5 7 11)) (push 2 *primes*) ``` Then `*primes*` is now `(2 3 5 7 11)`. So far, so good. Now I try to do the same thing, but without the `*primes*` variable, i.e.: ``` (push 2 '(3 5 7 11)) ``` The result is an error message: EVAL: 3 is not a function name; try using a symbol instead Now I have two questions: - Why does this not work? I would expect that `push` returns the list `(2 3 5 7 11)`, why does this not happen? Where am I wrong? - Apart from that, I don't get the error message. What is Lisp trying to tell me with `3 is not a function name`? Of course, `3` is not a function name, but I don't try to call a function named `3` anywhere, do I? Any help is appreciated :-)