First of all, let me say I'm a beginner in Lisp. To be honest I have been a beginner for some time now, but there are still many things I don't know well.
While I was writing this question, I came up with a strange bug in my code.
Here is a function that will return the list (0 1 ... n)
with the list e
appended. It uses rplacd
along the way to keep track of the last element, to avoid a final call to last
.
For example, (foo 4 '(x))
returns (0 1 2 3 4 x)
.
The "head" is stored in a
, which is not simply nil
, because there is only one nil
, and never a copy of it (if I understand correctly), hence I can't simply append to nil
.
(defun foo (n e)
(let* ((a (list nil)) (tail a))
(loop for i to n
do (rplacd tail (setf tail (list i)))
finally (rplacd tail (setf tail e))
(return (cdr a)))))
(defun bar (n e)
(let* ((a '(nil)) (tail a))
(loop for i to n
do (rplacd tail (setf tail (list i)))
finally (rplacd tail (setf tail e))
(return (cdr a)))))
The only difference between these functions is the (list nil)
replaced by '(nil)
in bar
. While foo
works as expected, bar
always returns nil
.
My initial guess is this happens because the original cdr
of a
is indeed nil
, and the quoted list may be considered constant. However, if I do (setf x '(nil)) (rplacd x 1)
I get (nil . 1)
as expected, so I must be at least partially wrong.