Common Lisp:(setf (car ...) (append ...))为何生成循环列表及与重复问题的差异
为什么这个Lisp操作会生成循环列表?
嘿,我最近在调试一段Lisp代码时遇到了个困惑,明明觉得不该生成循环列表,但结果却偏偏无限循环了,来跟大家说说具体情况:
首先执行这段代码:
(progn (setf (car *x*) (append '(3) *x*)) 2)
执行后返回了2,看起来设置值的时候没什么明显问题,但当我尝试打印*x*的时候,却陷入了无限循环。我实在搞不懂为什么*x*会变成循环列表——我完全没预料到这个结果啊!
问题根源
其实问题出在(car *x*)的赋值操作上。假设最初*x*是一个非空列表,比如(a b c),那(car *x*)就是列表的第一个元素a。当你执行(setf (car *x*) (append '(3) *x*))时,你把*x*的第一个元素替换成了(3 . *x*)(因为append '(3) *x*会生成一个以3开头、后面跟着原*x*的新列表)。
这就相当于把*x*的第一个元素指向了整个*x*本身,形成了一个环形结构:原*x*的第一个位置现在指向的列表,它的cdr部分又回到了原*x*,自然在打印的时候会无限递归下去,看起来就是循环列表了。
和类似问题的区别
另外我想强调一下,这个问题和之前的重复问题不一样——那些问题里的用户可能预期到循环列表的产生,而我是完全没想到会出现这种情况,核心困惑点在于我对setf修改car的行为会导致结构闭环这件事毫无察觉。
内容的提问来源于stack exchange,提问作者Makketronix
相关产品推荐
相关产品推荐

