clojure中惰性过滤器的实现

clojure中惰性过滤器的实现,clojure,lazy-sequences,Clojure,Lazy Sequences,在上,过滤器的定义如下: (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

在上,
过滤器
的定义如下:

(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))))

递归调用是对
过滤器
,而不是对
步骤
重要吗?如果是,原因是什么?

它与这里给出的其余代码一起,因为是
过滤器
惰性序列中进行包装。如果
step
调用自身,它将一次完成所有过滤,而不是惰性地进行过滤

(更新)如果
lazy seq
被添加到
step
的主体中,那么
step
可以调用自己,并且仍然是懒惰的。这至少可以通过以下两种方式实现:

  • 将整个主体包装在
    lazy seq
    中,并将对
    filter
    的递归调用和对
    recur
    的调用替换为对
    步骤的调用;注意。在这种情况下,需要命名
    步骤
    函数(通过将
    let
    替换为
    letfn
    ,并对语法进行适当更改,或者通过向
    fn
    表单添加名称:
    (fn步骤…
    );然后,
    lazy seq
    将最外层的调用包装到
    步骤
    将是不必要的;此外,在这一点上,您可能根本没有内部助手函数(只需直接在
    过滤器中使用此方法即可)

  • lazy seq
    保留在
    filter
    中,并将递归调用包装在
    step
    中(现在将是
    step
    本身),包装在
    lazy seq
    中(保持
    recur
    表单不变)


  • 请注意,
    clojure.core/filter
    具有不同的实现,具有单独的逻辑处理分块序列,并且没有内部帮助函数。在非分块的情况下,它的操作类似于第1节中描述的
    步骤版本。上面。

    但是如果我用
    惰性序列
    包裹整个身体,那么
    重复
    就不会在后面了position@tempestadept对,您必须用另一个递归调用替换它。(
    clojure.core/filter
    在非分块的情况下有效地工作。)我编辑了答案以考虑这一点。