Lisp:如何停止不需要的多个列表变量的重新分配

Lisp: How to stop unwanted reassignment of multiple list variables

在 lisp 中,我有以下示例代码:

(setf list1 '("a" "b" "c" )) 
(setf list2 '())
(setf list2 list1)
(setf (nth 2 list1) "d")
(princ list1)
(princ list2)

我想要的结果是:

(a b d)(a b c)

但它重新分配了 'list1' 和 'list2' 的第 n 个元素,导致:

(a b d)(a b d) 

我假设这是因为我在代码的前面将 list2 设置为等于 list1,但通常当您将变量设置为彼此相等时,它们不会那样改变。这里发生了什么?

万一没人能帮我,我想出了一个解决方案来解决这个问题,虽然它不是很优雅:

(setq list1 '("a" "b" "c")) 
(setq list2 '())
(setq i 0) 
(loop 
(setf list2 (append list2'(0)))
(setf (nth i list2)(nth i list1))
(setq i (+ i 1))
(when (= i (list-length list1)) (return)))
(setf (nth 2 list1) "d")
(princ list1)
(princ list2)

还是很好奇为什么(setf (nth N L) T)会重置所有已经用set相等的列表的第n个元素。

当您在 lisp 中分配列表时,不会发生复制。您问题的第三行:

(setf list2 list1)

不复制列表,而是将 list2 设置为也引用与 list1 相同的 cons 单元格。如果您想要一个新列表,请改用 copy-list:

(setf list2 (copy-list list1))

这会将 list2 设置为 list1 的浅表副本;也就是说list1和list2中CONS单元格的所有CAR都是same.