我们说我运行以下
(loop for i to 4 collect i)
然后我得到一个列表(0 1 2 3 4)
。现在,如果我想在结果中附加某些内容,我可以在其rplacd
元素上使用last
,但由于Lisp列表是链接列表,因此效率不高。这里的列表非常小,但它只是一个例子。
但是,由于循环工具按递增顺序返回列表,因此必须跟踪指向最后一个元素的指针,并使用rplacd
或等效的结果更新结果。 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)))))
答案 0 :(得分: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)
答案 1 :(得分:4)
问题:有没有办法使用这个"指针"在finally子句中?它允许一个人在结果上附加一些东西,也就是说 有时很有用。
我认为答案是"没有"。 finally子句的语法在:
中给出java -classpath C:\...\Metro\seaglasslookandfeel-0.2.jar;. Metro
当然,您可以将收集到某个特定变量中,然后附加或者使用nconc:
initial-final::= initially compound-form+ | finally compound-form+
这确实涉及额外的结果,但这可能是不可取的。 (我认为这是你想要避免的。)
另一个选择是使用 nconc 而不是收集来构建列表。如果您正在使用收集,那么您只需一次获取一个值然后再收集它。你可以将这一个值放入一个列表中,然后"收集"它与 nconc 。如果将一个元素列表保存到循环中的变量中,则可以引用它,它几乎就是尾指针。 E.g:
CL-USER> (loop for i from 1 to 5
collect i into ns
finally (return (nconc ns (list 'a 'b 'c))))
;=> (1 2 3 4 5 A B C)
在标有***的行中,对 nconc 的调用只需要遍历 ilist 的最终值,即(5)。这是一个非常快速的 nconc 电话。