附加到“循环收集"的结果.在Lisp中 [英] Appending to the result of a "loop-collect" in Lisp

查看:81
本文介绍了附加到“循环收集"的结果.在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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆