Common Lisp中如何去除列表中的点?append/nconc使用疑问
Lisp列表末尾的点是什么?怎么解决?
那个点的含义
Lisp里的点代表这个结构不是标准列表。标准列表是一串嵌套的cons单元,最后一个cons的cdr必须是nil。比如(B C D E)本质是(B . (C . (D . (E . nil)))),打印时会省略末尾的. nil。而你得到的(B C D E . A),说明最后一个cons的cdr是A(不是nil),所以打印时会显式标出这个点,这种结构叫「点列表(dotted list)」。
为什么会出现这个问题
你应该是写了类似这样的代码:
(append (cdr '(A B C D E)) (car '(A B C D E)))
append要求所有参数都是列表,但(car lst)取出来的是单个元素A,不是列表。这时候append会把这个元素直接当成最后一个cons的cdr,导致结构不完整,变成点列表。用nconc时同理,直接把单个元素接到列表末尾,也会修改最后一个cons的cdr为元素本身,而非nil。
解决办法
把要放到末尾的元素包装成单元素列表再拼接就行:
- 用
append(创建新列表,不修改原列表):
(append (cdr lst) (list (car lst)))
比如输入'(A B C D E),结果就是(B C D E A),标准列表,不会有点。
- 用
nconc(修改原列表的末尾,注意副作用):
(nconc (cdr lst) (list (car lst)))
同样能得到标准列表,但要注意nconc会改变原(cdr lst)的结构,后续再用原列表可能会有意外。
内容的提问来源于stack exchange,提问作者M1ctl4nt3cutl1
相关产品推荐
相关产品推荐

