I';我很难理解为什么当我更改列表中的某些值时,某些Lisp数据会更改,而其他数据则不会更改';T

I';我很难理解为什么当我更改列表中的某些值时,某些Lisp数据会更改,而其他数据则不会更改';T,lisp,common-lisp,clisp,Lisp,Common Lisp,Clisp,我很难理解为什么当我更改l1列表的值时,double args宏会更改结果列表中的值,而double列表不会。让我更清楚地说明步骤。 我已经用值(1 2 3 4)定义了列表l1 然后我在下面加载这个代码 (defmacro double-args (&rest args) `(let ((ret nil)) ( dolist (x ,@args ) (setq ret (append ret (list x x)))) ret) ) (d

我很难理解为什么当我更改l1列表的值时,double args宏会更改结果列表中的值,而double列表不会。让我更清楚地说明步骤。 我已经用值(1 2 3 4)定义了列表l1

然后我在下面加载这个代码

    (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))
在此之后,我使用列表l1执行了宏macroteste,并将其存储在l2中

 (setq l2 (macroteste l1))
然后,我用arg l1执行doublelistmacro并将其存储在l3中

 (setq l3 (doublelistmacro l1))
所以我从l2开始, ((1 2 3 4) (1 2 3 4)) 从l3开始, (1 12 3 4 4)

然后我改变了l1的第二个值, (setf(北1 l1)9) 我得到了这些结果:

l1

(19 3 4)

l2

((1934)(1934))

l3

(1 12 3 4 4)


为什么当我改变l1时,l2也改变了,而l3没有改变?

首先,请注意:在代码中,您不应该修改像
'(1 2 3 4)
这样的文字常量。影响尚未定义

在你的情况下,差异归结为这一点

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)
第一个列表
l1
是一个新列表,其元素是原始列表的两倍。 第二个列表
l2
是一个全新构建的列表

如果更改原始列表,它将在第一个结果中可见->它将它们直接作为元素

它在第二个列表中不可见,因为该列表是完全新的

还请注意,宏使问题复杂化。因此,它们也没有什么意义

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)