为什么我的惰性递归Clojure函数被实现了?

Why is my lazy recursive Clojure function being realized?

我正在尝试解决一个 4Clojure 问题(序列缩减),但我碰壁了。问题是重新实现reductions函数。

在我看来这个函数 应该 return 是一个惰性序列,但它不是 - 评估 (take 5 (redux + (range))) 会导致无限循环。

这是我的代码:

(defn redux
  ([f coll] 
      (redux f (first coll) (rest coll)))
  ([f val coll] 
      ((fn red [val coll s]
           (if (empty? coll)
               s
               (lazy-seq
                  (let [val (f val (first coll))]
                    (red val 
                         (rest coll)
                         (conj s val))))))
       val coll [val])))

为什么这个函数不是 return惰性序列?

代码中存在一些误解。 noisesmith 在#clojurians 聊天(以及 Josh 的评论中也指出)指出以下几点:

  1. 上述函数中没有任何步骤可以计算列表的头部而不是列表的尾部。
  2. 直接自递归,要得到第n+1个元素需要递归调用
  3. lazy-seq 应该总是调用 cons 或一些类似的函数,让你 return 列表的下一项而不重复。
  4. conj从不懒惰,向量从不懒惰。
  5. 你不能在没有意识到整个事情的情况下附加到列表。

我修改了代码如下:

(fn redux
  ([f coll] 
      (redux f (first coll) (rest coll)))
  ([f val coll] 
      (cons val
        ((fn red [val coll]
           (lazy-seq
             (when-not (empty? coll)
               (let [val (f val (first coll))]
                 (cons val (red val (rest coll)))))))
          val coll))))

注意使用 cons 而不是 conj