为什么我的惰性递归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 的评论中也指出)指出以下几点:
- 上述函数中没有任何步骤可以计算列表的头部而不是列表的尾部。
- 直接自递归,要得到第n+1个元素需要递归调用
lazy-seq
应该总是调用 cons
或一些类似的函数,让你 return 列表的下一项而不重复。
conj
从不懒惰,向量从不懒惰。
- 你不能在没有意识到整个事情的情况下附加到列表。
我修改了代码如下:
(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
。
我正在尝试解决一个 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 的评论中也指出)指出以下几点:
- 上述函数中没有任何步骤可以计算列表的头部而不是列表的尾部。
- 直接自递归,要得到第n+1个元素需要递归调用
lazy-seq
应该总是调用cons
或一些类似的函数,让你 return 列表的下一项而不重复。conj
从不懒惰,向量从不懒惰。- 你不能在没有意识到整个事情的情况下附加到列表。
我修改了代码如下:
(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
。