附加到“循环收集"的结果.在Lisp中 [英] Appending to the result of a "loop-collect" in Lisp
问题描述
假设我运行以下
(loop for i to 4 collect i)
然后我得到一个列表(0 1 2 3 4)
.现在,如果我想在结果中添加一些内容,可以在last
元素上使用rplacd
,但是由于Lisp列表是链接列表,因此效率不是很高.这里的列表很小,但这只是一个例子.
Then I get a list (0 1 2 3 4)
. Now, if I want to append something to the result, I may use rplacd
on its last
element, but since Lisp lists are linked lists, it's not very efficient. Here the list is ridiculously small, but it's only an example.
但是,由于循环工具以递增的顺序返回列表,因此它必须跟踪指向最后一个元素的指针,并用rplacd
或类似的东西更新结果. macroexpand-all
表示这是CCL的功能,也可能是其他形式的.
However, since the loop facility returns the list in increasing order, it has to keep track of a pointer to the last element, and update the result with rplacd
, or something equivalent. A macroexpand-all
shows it's what CCL does, and probably other lisps too.
问题:是否可以在finally
子句中使用此指针"?它将允许人们在结果中附加一些内容,这有时很有用.
Question: Is there a way to use this "pointer" in the finally
clause? It would allow one to append something to the result, which is sometimes useful.
当然,编写指针机制很容易,但并不是很好.例如,以下内容会将列表e
追加到列表(0 1 ... n)
.
Of course, it's easy to code the pointer machinery, but it's not so nice. For example, the following will append the list e
to the list (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)))))
推荐答案
每次迭代的额外比较和一次额外的迭代会为您提供:
An additional comparison for each iteration and one additional iteration gives you this:
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)
这篇关于附加到“循环收集"的结果.在Lisp中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!