附加到Lisp中的"循环收集"结果

10 lisp loops common-lisp

假设我运行以下内容

(loop for i to 4 collect i)
Run Code Online (Sandbox Code Playgroud)

然后我得到一个清单(0 1 2 3 4).现在,如果我想在结果中添加一些内容,我可以使用rplacd它的last元素,但由于Lisp列表是链表,因此效率不高.这里的清单非常小,但这只是一个例子.

但是,由于循环工具以递增的顺序返回列表,因此它必须跟踪指向最后一个元素的指针,并使用rplacd或等效的更新结果.A macroexpand-all显示它是CCL的作用,也可能是其他lisps.

问题:有没有办法在finally条款中使用这个"指针" ?它允许一个人在结果上附加一些东西,这有时是有用的.

当然,编码指针机制很容易,但它并不是那么好.例如,以下内容将列表附加e到列表中(0 1 ... n).

(defun foo (n e)
    (let* ((a (list nil)) (tail a))
        (loop for i to n
              do (rplacd tail (setf tail (list i)))
              finally (rplacd tail (setf tail e))
              (return (cdr a)))))
Run Code Online (Sandbox Code Playgroud)

Rai*_*wig 7

每次迭代和一次额外迭代的额外比较为您提供:

CL-USER 2 > (defun foo (n e &aux (z (1+ n)))
              (loop for i to z
                    unless (= i z)
                      collect i
                    else
                      nconc e))
FOO

CL-USER 3 > (foo 4 '(f o o))
(0 1 2 3 4 F O O)
Run Code Online (Sandbox Code Playgroud)

  • @ Jean-ClaudeArbaut:既然你自己发现`LOOP`实现跟踪最后的缺点并验证它扩展代码宏,看起来你有一个良好的开端.;-) (3认同)