在http://clojure.org/lazy上,filter
以这种方式定义:
(defn filter
"Returns a lazy sequence of the items in coll for which
(pred item) returns true. pred must be free of side-effects."
[pred coll]
(let [step (fn [p c]
(when-let [s (seq c)]
(if (p (first s))
(cons (first s) (filter p (rest s)))
(recur p (rest s)))))]
(lazy-seq (step pred coll))))
递归调用是filter
,而不是step
是否重要?如果是,为什么?
答案 0 :(得分:1)
这是与此处给出的其余代码一样,因为它是filter
,它在lazy-seq
中进行包装。如果step
自己调用,它会立即进行所有过滤,而不是懒惰。
(已更新。)如果将lazy-seq
添加到step
的正文中,则step
可以自行调用并仍然是懒惰的。这至少可以通过以下两种方式实现:
将整个正文包裹在lazy-seq
中,并通过调用filter
替换递归调用recur
和step
; NB。在这种情况下,需要命名step
函数(通过将let
替换为letfn
,使用适当的语法更改,或者为{{1}添加名称} form:fn
);然后将(fn step ...)
包裹最外面的lazy-seq
调用是不必要的;此外,你可能根本就没有内部帮助函数(直接在step
中使用这种方法);
将filter
保留在lazy-seq
中,并将filter
中的递归调用(现在将step
本身包含在{{1}中)包装(step
形式保持不变)。
请注意,lazy-seq
具有不同的实现,具有单独的逻辑处理分块序列而没有内部辅助函数。在非分块的情况下,它的操作类似于上面1.中描述的recur
版本。