I'm struggling two understand why when i change the values of l1 list the double-args macro changes the value in the result list and the double-list doesn't. Let me show the steps to be more clear. I have defined the list l1 with values '(1 2 3 4),
(setq l1 '(1 2 3 4))
then i load this code below
(defmacro double-args (&rest args)
`(let ((ret nil))
( dolist (x ,@args )
(setq ret (append ret (list x x))))
ret) )
(defun macroteste (&rest x) (double-args x))
;; first simple macro example:
(defmacro double-list (a-list)
(let ((ret (gensym)))
`(let ((,ret nil))
(dolist (x ,a-list)
(setq ,ret (append ,ret (list x x))))
,ret)))
;; use the macro:
(defun doublelistmacro (x)
(double-list x))
after this, i had executed the macro, macroteste with the list l1 and stored in l2
(setq l2 (macroteste l1))
then i executed the doublelistmacro with arg l1 and stored in l3
(setq l3 (doublelistmacro l1))
so i got from l2, ((1 2 3 4) (1 2 3 4)) and from l3, (1 1 2 2 3 3 4 4)
then i had change the second value of l1, (setf (nth 1 l1) 9) and i got theses results:
l1
(1 9 3 4)
l2
((1 9 3 4) (1 9 3 4))
l3
(1 1 2 2 3 3 4 4)
why when i changed l1 the l2 has changed too but l3 not?
First, a remark: in code you should not modify literal constants like '(1 2 3 4)
. The effects are undefined.
In your case the difference boils down to this
CL-USER 2 > (let ((foo (list 1 2 3 4)))
(let ((l1 (list foo foo))
(l2 (loop for e in foo append (list e e))))
(values l1 l2)))
((1 2 3 4) (1 2 3 4))
(1 1 2 2 3 3 4 4)
The first list l1
is a new list with the original list twice as its element.
The second list l2
is a completely new constructed list.
If you change the original list, it will be visible in the first result -> it has them directly as elements.
It will not be visible in the second list, because the list is completely fresh.
Note also that the macros are complicating the issue. As such they also make very little sense.