推送宏存储在功能内但不退出功能



我有一个函数:

(defun multi-push (L P)
(print (if L "T" "F"))
(print P)
(when L
(multi-push (cdr L) (push (car L) P)))
P)

我试图将一个列表推送到另一个列表(我知道输入列表L是相反的。这是设计使然(。打印语句是有意义的,但是当我查看变量P时,它并没有像我预期的那样发生突变。

示例 REPL 输出:

CL-USER> bob
(3 3 3)
CL-USER> (multi-push (list 1 2) bob)
"T"
(3 3 3)
"T"
(1 3 3 3)
"F"
(2 1 3 3 3)
(1 3 3 3)
CL-USER> bob
(3 3 3)

我做错了什么?我认为PUSH(根据[http://clhs.lisp.se/Body/m_push.htm](改变了它的第二个论点。我还尝试过POPL并将其PUSHP上的变化,然后再LP调用multi-push

需要注意的一点是,(1 3 3 3)行是multi-push函数的输出。这也让我感到困惑。

push破坏性地变异的是绑定,而不是列表。 更准确地说,push修改的是一个"地方",它是

适合用作广义参考的表格

其中"广义引用"是

对存储对象的位置的引用,就像对变量一样。

这两句话来自CLHS词汇表:讨论这个问题的部分是5.1。

特别:

> (let* ((l1 '(1 2 3))
(l2 l1))
(push 0 l1)
(values l1 l2))
(0 1 2 3)
(1 2 3)

还要注意,这是合法CL,因为它不会破坏性地改变引用的列表结构。push必须是一个宏,因为函数不能做它所做的事情:你不能编写一个函数f这样:

(让* ((A (列表 1 2 3(( (二(( (fa b( (不是(等式 b(((

会是真的。

你可以把(push x y)想象成扩展到类似(setf y (cons x y))的东西,除了它会正确地处理多重求值。

最新更新