我很难理解为什么当我改变列表中的某些值时某些 Lisp 数据会发生变化而其他人不会
I'm struggling to understand why some Lisp data changes when I alter some value in a list and others doesn't
我正在努力理解为什么当我更改 l1 列表的值时,双参数宏会更改结果列表中的值,而双列表不会。让我展示更清楚的步骤。
我已经用值 '(1 2 3 4),
定义了列表 l1
(setq l1 '(1 2 3 4))
然后我在下面加载这段代码
(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 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 没有?
首先,请注意:在代码中,您不应该修改像 '(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
是一个全新构造的列表。
如果您更改原始列表,它将在第一个结果中可见 -> 它直接将它们作为元素。
不会出现在第二个列表中,因为列表是完全新鲜的。
另请注意,宏使问题复杂化。因此,它们也没有什么意义。
我正在努力理解为什么当我更改 l1 列表的值时,双参数宏会更改结果列表中的值,而双列表不会。让我展示更清楚的步骤。 我已经用值 '(1 2 3 4),
定义了列表 l1(setq l1 '(1 2 3 4))
然后我在下面加载这段代码
(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 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 没有?
首先,请注意:在代码中,您不应该修改像 '(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
是一个全新构造的列表。
如果您更改原始列表,它将在第一个结果中可见 -> 它直接将它们作为元素。
不会出现在第二个列表中,因为列表是完全新鲜的。
另请注意,宏使问题复杂化。因此,它们也没有什么意义。