在emacs lisp中使用nconc的奇怪行为
我有以下功能(简化为该版本): 如果我多次计算函数在emacs lisp中使用nconc的奇怪行为,emacs,elisp,Emacs,Elisp,我有以下功能(简化为该版本): 如果我多次计算函数(append test'((foo))列表的大小会不断增加,但我不明白为什么。ncoc修改原始列表,但是因为原始列表是函数参数或let变量,所以每次调用都应该重新创建它们,对吗?这里发生了什么?如果将`(条形)更改为(列表条形),则代码每次都返回相同的结果 ncoc修改除最后一个参数外的所有参数。显然,如果第一个参数是”(bar),那么函数定义中包含的引用列表将被修改,我们希望看到您看到的结果。显然,使用不包含任何逗号的反引号表达式等同于使用带
(append test'((foo))
列表的大小会不断增加,但我不明白为什么。ncoc
修改原始列表,但是因为原始列表是函数参数或let变量,所以每次调用都应该重新创建它们,对吗?这里发生了什么?如果将`(条形)
更改为(列表条形)
,则代码每次都返回相同的结果
ncoc
修改除最后一个参数外的所有参数。显然,如果第一个参数是”(bar)
,那么函数定义中包含的引用列表将被修改,我们希望看到您看到的结果。显然,使用不包含任何逗号的反引号表达式等同于使用带引号的列表
实际上,下面的代码保留了反引号,但在列表的cdr中添加了一个无意义的表达式。显然,这使得它在每次调用函数时都分配一个新列表,因此每次都返回相同的结果:
(defun append-test (xs)
(let ((ys `(foo ,(nconc `(bar . ,(ignore)) xs))))
(nconc ys `((baz)))))
我被这个咬了。下面是一些导致的错误 这个问题似乎是lisp开发人员的必经之路。:-) 据我所知,lisp评估分为两个阶段:
报价
呢?
quote
只返回已读表单,无需计算
含蓄地
报价
表单时,它只返回分配的读卡器
直接反对报价
表单(即函数调用等)时,它返回
同一个读卡器分配的对象引用
不分配新内存塔达 你能详细说明一下吗?xs是一个参数,ys是let变量,其余的列表是函数返回值(引号或列表)。对于每个函数调用,所有这些都应该是“新的”,但很明显,其中一些是由nconc共享和修改的。共享的是第一次
nconc
调用中的(条形)
列表。它在函数定义中保留为带引号的值,因此每次调用ncoc
时它的值都会发生变化。@Masse不要混淆分配和绑定<代码>让绑定,但它不会自行分配新存储。分配取决于绑定的右侧,带引号的列表由读取器静态分配,因此您的let
在每次调用时绑定到相同的静态分配列表。考虑下面的更简单的例子:可能的副本
(defun append-test (xs)
(let ((ys `(foo ,(nconc `(bar . ,(ignore)) xs))))
(nconc ys `((baz)))))