【发布时间】:2015-07-05 06:21:41
【问题描述】:
首先,让我说我是 Lisp 的初学者。说实话,我初学者也有一段时间了,但还是有很多东西不是很了解。
在我写this question 的时候,我在我的代码中发现了一个奇怪的错误。
这是一个函数,它将返回列表(0 1 ... n),并附加列表e。它一路使用rplacd 来跟踪最后一个元素,以避免最终调用last。
例如,(foo 4 '(x)) 返回(0 1 2 3 4 x)。
“头”存储在a,而不是简单的nil,因为只有一个nil,而且从来没有它的副本(如果我理解正确的话),所以我不能简单地追加到nil。
(defun foo (n e)
(let* ((a (list nil)) (tail a))
(loop for i to n
do (rplacd tail (setf tail (list i)))
finally (rplacd tail (setf tail e))
(return (cdr a)))))
(defun bar (n e)
(let* ((a '(nil)) (tail a))
(loop for i to n
do (rplacd tail (setf tail (list i)))
finally (rplacd tail (setf tail e))
(return (cdr a)))))
这些函数之间的唯一区别是bar 中的(list nil) 替换为'(nil)。虽然 foo 按预期工作,但 bar 始终返回 nil。
我最初的猜测是发生这种情况是因为a 的原始cdr 确实是nil,并且引用的列表可能被认为是不变的。但是,如果我执行(setf x '(nil)) (rplacd x 1),我会按预期得到(nil . 1),所以我必须至少部分错误。
【问题讨论】:
-
bar的括号似乎不平衡。 -
@user2357112 已更正。缺少的结束括号就在
'(nil)之后。对此感到抱歉。 -
我不熟悉Common Lisp,但我相信Scheme,任何用
'引用的东西都应该被视为不可变的。这适用于 Common Lisp 吗?看起来你正试图改变这个东西。 -
@user2357112 是的,我从过去使用 Scheme 的经验中记得这一点。在 Common Lisp 中,它似乎不一样。但我很谨慎,因为我怀疑我的错误与此有关。
-
我的另一个猜测是,在一个版本中,您将获得一个带有符号
nil的列表,而在另一个版本中,nil被评估为一个空列表。编辑:不,看起来符号nil计算结果为符号nil。
标签: lisp common-lisp literals