我正在努力理解为什么当我更改列表中的某些值时某些 Lisp 数据会发生变化而其他的则不会

Joã*_*ade 0 lisp clisp common-lisp

我正在努力理解为什么当我更改 l1 列表的值时,双参数宏会更改结果列表中的值而双列表不会。让我把步骤展示得更清楚。我已经用值 '(1 2 3 4) 定义了列表 l1,

(setq l1 '(1 2 3 4))
Run Code Online (Sandbox Code Playgroud)

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

    (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))
Run Code Online (Sandbox Code Playgroud)

在此之后,我执行了宏,macroteste 与列表 l1 并存储在 l2

 (setq l2 (macroteste l1))
Run Code Online (Sandbox Code Playgroud)

然后我用 arg l1 执行了 doublelistmacro 并存储在 l3 中

 (setq l3 (doublelistmacro l1))
Run Code Online (Sandbox Code Playgroud)

所以我从 l2, ((1 2 3 4) (1 2 3 4)) 和 l3, (1 1 2 2 3 3 4 4)

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

l1

(1 9 3 4)

l2

((1 9 3 4) (1 9 3 4))

l3

(1 1 2 2 3 3 4 4)

为什么当我更改 l1 时 l2 也发生了变化而 l3 没有?

Rai*_*wig 6

首先,请注意:在代码中你不应该修改像'(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)
Run Code Online (Sandbox Code Playgroud)

第一个列表l1是一个新列表,它的元素是原始列表的两倍。第二个列表l2是一个全新构建的列表。

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

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

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