为什么 setq 什么都不做?

Why is setq not doing anything?

我需要使用 setq 更新嵌套在另一个关联列表中的关联列表中的值。我还不知道该怎么做,但我发现如何做的第一步没有奏效。

尽可能简单地说这是我尝试过的:

(defvar l (list 1 2 3))
(loop for x in l do (setq x 5))

我希望这会将 l 中的所有元素更新为 5,但是当我检查 l 的值时,它根本没有改变。如果它不适用于此示例,那么显然它不适用于我的嵌套列表场景。我如何遍历 l 并更改元素? 另外,如果 l 没有更新,那么 (setq x ...) 甚至在做什么?

编辑我决定继续使用常规的关联列表列表,但我仍然卡住了

(defvar u (list (list 1 2) (list 3 4)))
(assoc 1 u)
=> (1 2)
(let ((a (assoc 1 u))) (setf (assoc u 1) (cons (car a) 5)))

我希望您更改为 ((1 5) (3 4)) 但我收到错误 函数 (SETF ASSOC) 未定义。如果 assoc 没有内置的 setf 形式,那么肯定有一些其他的内置函数可以做到这一点吧?

首先,关联列表(reference)是一个列表,其中一个元素是cons对,其car就是所谓的key ,而 cdr。所以,如果你想建立一个键和值都是数字的关联列表,正确的形式是:

(defvar *u* (list (cons 1 2) (cons 3 4))
(assoc 1 *u*) ; => (1 . 2)

这样,当你想修改与某个键关联的值时,你可以使用rplacd原语操作(reference),即替换assoc 找到的一对 cdr。例如:

(rplacd (assoc 1 *u*) 5)
*u* ; => ((1 . 5) (3 . 4))

请注意,setq 可用于修改变量,而不是数据结构,如对或列表。

I need to update values in an association list nested in another association list using setq.

不适用于 setqever,它会更改变量的绑定;但有时 (setf (car ...(setf (cdr ...(两个 翻译成 rplacarplacd)。

为什么有时候?取决于您是否有权访问结构本身或其副本。例如(loop for x on l do (setf car x) 5) 不会更新 l,但 (maplist #'(lambda(x) (setf (car x) 6)) l) 会更新,(setf (car l) 7).

也会更新
(loop for x in l do (setq x 5))

l是外层变量。

x 是局部变量。循环创建局部变量并将列表项绑定到每个循环中的变量。

如果您设置变量 x,那么您只需更改该变量绑定。它对列表没有影响,因为 x 有自己的元素引用。它不引用列表存储单元。