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

时间:2017-08-30 21:33:46

标签: clojure lazy-evaluation

我正在尝试解决4Clojure问题(序列减少),而且我已经碰壁了。问题是重新实现reductions功能。

在我看来,这个函数应该返回一个惰性序列,但它没有 - 评估(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])))

为什么这个函数没有返回一个懒惰的序列?

1 个答案:

答案 0 :(得分:2)

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

  1. 上述功能中没有步骤可以评估列表的头部而不是列表的尾部。
  2. 它会立即进行自我递归,要获得n + 1个元素,您需要进行递归调用。
  3. lazy-seq应始终调用cons或某些类似的函数,以便您返回列表的下一项而不会重复出现。
  4. conj从不懒惰,矢量永远不会懒惰。
  5. 如果没有意识到整件事情,你就无法附加到列表中。
  6. 我将代码修改为以下内容:

    (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