Here are two simple functions that use push
on a variable passed in:
(defun push-rest (var) (push 99 (rest var)))
and
(defun just-push (something) (push 5 something))
The first one will permanently mutate the var
passed. The second does not. This is quite confusing for someone who is learning the scoping behavior of this language:
CL-USER> (defparameter something (list 1 2))
SOMETHING
CL-USER> something
(1 2)
CL-USER> (just-push something)
(5 1 2)
CL-USER> something
(1 2)
CL-USER> (push-rest something)
(99 2)
CL-USER> something
(1 99 2)
In push-rest
why isn't the var's scope local to the function like in just-push
, when they are both using the same function, push
?
According to Peter Siebel's Practical Common Lisp, Chapter 6. Variables: This might help you a lot:
And a footnote:
(Pass by value also essentially means copy; but we aren't copying the object; we are copying the reference/pointer to the object.)
As I noted in another comment:
Lisp doesn't pass objects. Lisp passes copies of object references to functions. Or you could think of them as pointers.
setf
assigns a new pointer created by the function to something else. The previous pointer/binding is not touched. But if the function instead operates on this pointer, rather than setting it, then it operates on the original object the pointer points too. if you are a C++ guy, this might make much more sense for you.