List 连接列表并将结果返回到第一个参数中
我想知道在Common Lisp中做这样的事情最有效(通常)和可读的方式是什么:List 连接列表并将结果返回到第一个参数中,list,functional-programming,append,concatenation,common-lisp,List,Functional Programming,Append,Concatenation,Common Lisp,我想知道在Common Lisp中做这样的事情最有效(通常)和可读的方式是什么: (setq result-list (append result-list small-list)) 也就是说,是否有类似于(以破坏性方式追加结果列表小列表)的东西可以确保结果列表包含连接的列表 我这样做是为了提高可读性,但对于(函数式)编程实践来说,这是个好主意吗 但是,请注意,您仍然需要这样做 (setf result-list (nconc result-list small-list)) 因为如果结果
(setq result-list (append result-list small-list))
也就是说,是否有类似于(以破坏性方式追加结果列表小列表)
的东西可以确保结果列表
包含连接的列表
我这样做是为了提高可读性,但对于(函数式)编程实践来说,这是个好主意吗
但是,请注意,您仍然需要这样做
(setf result-list (nconc result-list small-list))
因为如果结果列表
为nil
,则(NCOC结果列表小列表)
是小列表
,结果列表
未修改
另一个需要注意的问题是ncoc
和append
都是
在结果列表
长度中是线性的,所以这不是一个很好的方法
存储大量数据。看看你的问题,我将猜测你想要什么,并给出一些提示,如果你想重复扩展列表,但不想一次又一次地扫描它 如果您处于循环中,则可以使用
收集
、追加
、或ncoc
(defun nconcat (lists)
(loop for list in lists nconc list))
如果您想在更一般的设置中执行此操作,那么想法是跟踪列表的末尾,以便追加只需扫描短列表。例如:
(defun nconcat (lists)
(let* ((result-ref (list nil))
(end result-ref))
(mapc
(lambda (list)
(setf (cdr end) list
end (last end)))
lists)
(cdr result-ref)))
如果你不得不在同一张单子上一遍又一遍地做,
tail wagging
可能是最好的解决方案(我从Edi Weitz的书中了解到):
为*l*
的最后一个cons单元格指定一个名称
(defparameter *tail* (last *l*))
现在,(cdr*tail*)
是列表的最后一个元素:”()
。
假设您想在其末尾添加(列出'g'h'i)
。
将(setf
)分配给(cdr*tail*)
,这是列表*l*
的最后一个cons
-单元格:'()
,
并将(setf
)新的最后一个cons元素重新分配给tail
现在,*l*
被修改为包含第二个列表。
和*tail*
命名此新列表的最后一个cons
单元格
*l*
;; (a b c d e f g h i)
*tail*
;; (i)
下一次,当*tail*
必须通过列表扩展时,您不必再次遍历所有列表,只需将要追加的列表分配给*tail*
的cdr
,即可修改原始列表
顺便说一句,当我仔细思考时,我绊倒了
摇尾巴
,亚历山大港修改了宏APPENDF
和ncocf
。您也可以使用define-MODIFY-MACRO
轻松定义它们。我从未听说过define-MODIFY-MACRO
。这是通用的Lisp还是一些特定于实现的东西?这是通用的Lisp:我可以建议将解释移到注释之外吗?它们呈现为灰色文本,您会错过标记格式。“尾巴摆动”(以前从未听说过)又名“自上而下列表构造”又名“差异列表”。)你能举出Edi Weitz的书的书名吗?@gsl Common Lisp Recipes
(setf (cdr *tail*) (list 'g 'h 'i)
*tail* (last *tail*))
*l*
;; (a b c d e f g h i)
*tail*
;; (i)