If I have something like this,
(setq first (list 'a 'b 'c))
(setq second (list 'x 'y 'z))
;; I know the let binding makes little sense but
;; I need it in the full version of the function.
(defun return-list (list)
(let ((value list))
value))
and I evaluate
(setcdr (return-list first) (append (return-list second)))
then what object does setcdr
actually act on? On calling (return-list first)
after the setcdr
form I consistently get (a x y z)
. It seems to me that setcdr
traces back first
through the let binding and actually changes the value of the variable – indeed first
itself evaluates to (a x y z)
– but I'm not sure. The node about mutability on the Elisp manual says,
If a program attempts to change objects that should not be changed, the resulting behavior is undefined: the Lisp interpreter might signal an error, or it might crash or behave unpredictably in other ways.
When similar constants occur as parts of a program, the Lisp interpreter might save time or space by reusing existing constants or their components.
I'm not sure there isn't something that shouldn't be changed in my program. What I'd like to know is if I can rely on first
always being (a x y z)
after evaluating the setcdr
form.
first
? Typically, you don't want that as it makes programs hard to understand. A good rule of thumb is to limit destructive operations to lists created locally.point-stack--value
and it would require a major revision of my program to change the way it works.setcdr
modifies thecdr
of a cons cell. Lists are chains of any number of cons cells, but list values are passed around as the single cons cell which starts the list (or asnil
, the empty list). So yourfirst
andsecond
values, and yourlist
arg, are each pointers to a cons cell, and your let-boundvalue
variable (and therefore the return value of the function) point to the same cons cell as thelist
arg, which is the same cons cell asfirst
orsecond
respectively in your subsequent calls to that function. You have two lists, and a bunch of things pointing at them.