List 连接列表并将结果返回到第一个参数中

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)) 因为如果结果

我想知道在Common Lisp中做这样的事情最有效(通常)和可读的方式是什么:

(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)