我想知道在 Common Lisp 中做这样的事情最有效(algrotihmically)和可读的方式是什么:
(setq result-list (append result-list small-list))
也就是说,是否有类似 (append-destructively result-list small-list)
的东西可以确保 result-list
包含串联列表?
我这样做是为了提高可读性,但在(函数式)编程实践方面这是个好主意吗?
最佳答案
如果你必须在同一个列表上一遍又一遍地做,
tail-wagging
可能是最好的解决方案(这是我从 Edi Weitz 的书中学到的):
(defparameter *l* (list 'a 'b 'c 'd 'e 'f))
给*l*
的最后一个cons-cell起个名字
(defparameter *tail* (last *l*))
现在,(cdr *tail*)
是列表的最后一个元素:'()
。
假设您要将 (list 'g 'h 'i)
添加到其末尾。
将 (setf
) 分配给 (cdr *tail*)
这是最后一个 cons
-cell: '()
列表 *l*
,
并将新的最后一个 cons 元素重新分配 (setf
) 给 tail。
(setf (cdr *tail*) (list 'g 'h 'i)
*tail* (last *tail*))
现在,*l*
发生变异以包含第二个列表。
和 *tail*
命名这个新列表的最后一个 cons
单元格。
*l*
;; (a b c d e f g h i)
*tail*
;; (i)
下一次,当*tail*
需要扩展一个列表时,就不用再遍历所有列表了,直接赋值给cdr
即可> *tail*
的待追加列表,然后修改原始列表。
顺便说一句,我在考虑 tailp
时偶然发现了 tail-wagging
关于list - 连接列表并将结果返回到第一个参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50841328/