我有以下功能(简化为该版本):
(defun append-test (xs)
(let ((ys `(foo ,(nconc `(bar) xs))))
(nconc ys `((baz)))))
如果我多次评估函数(append-test '((foo)))
,列表的大小会不断增加,但我无法理解为什么。 nconc
修改原始列表,但由于原始列表是函数参数或let-variable,因此每次调用都应重新创建它们,对吧?这里发生了什么?
答案 0 :(得分:2)
如果您将`(bar)
更改为(list 'bar)
,则代码每次都会返回相同的结果。
nconc
修改所有参数,但最后一个参数。显然,如果第一个参数是'(bar)
,那么函数定义中包含的引用列表将被修改,我们希望看到您看到的结果。显然使用不包含任何逗号的反引号表达式等同于使用引用列表。
实际上,下面的代码保留了反引号,但是为列表的cdr添加了一个无意义的表达式。显然,这使得它在每次调用函数时都会分配一个新列表,因此每次都会返回相同的结果:
(defun append-test (xs)
(let ((ys `(foo ,(nconc `(bar . ,(ignore)) xs))))
(nconc ys `((baz)))))
答案 1 :(得分:1)
我被这个咬了。以下是一些导致的错误。
http://comments.gmane.org/gmane.emacs.bugs/50783
http://lists.gnu.org/archive/html/emacs-bug-tracker/2011-09/msg00220.html
这个问题似乎是lisp开发人员的成文。 : - )
quote
怎么样? quote
只返回读取表单而不进行评估。
隐含地,
quote
表单时,它只返回已分配的阅读器
直接对象。quote
表单(即函数调用等)时,它返回
同一个读者分配对象。quote
不分配新内存 钽哒!