Clojure 缩减函数
Clojure reduced function
我知道有 reduced
函数可以终止这样一个无限的东西,但我很好奇为什么在第二个版本中(range
没有 arg)它不会终止缩减,因为它达到150?
user=> (reduce (fn [a v] (if (< a 100) (+ a v) a)) (range 2000))
105
user=> (reduce (fn [a v] (if (< a 100) (+ a v) a)) (range))
因为,reduce 将函数应用于序列 (range) 中的每个元素,因此 (range) 完全实现了。
(range)
产生无限序列,
(fn [a v] (if (< a 100) (+ a v) a))
不会停止循环,它会应用于每个元素。
在 REPL 处执行
(reduce (fn [a v] (if (< a 100) (+ a v) a)) (range))
意味着我们很早就想获取并打印结果,因此 REPL 挂起。
正如你提到的,对于那些后来出现的人,谷歌搜索减少了。 reducing 函数确实有能力明确地声明归约的最终答案,并保证不会通过返回调用 (reduced the-final-answer)
的结果来消耗进一步的输入
user> (reduce (fn [a v]
(if (< a 100)
(+ a v)
(reduced a)))
(range))
105
在这种情况下,当新收集的结果超过 100 时,下一次迭代将停止减少,而不是将其值贡献给答案。这确实消耗了输入流中未包含在结果中的一个额外值。
user> (reduce (fn [a v]
(let [res (+ a v)]
(if (< res 100)
res
(reduced res))))
(range))
105
这会在达到阈值后立即完成缩减,并且不会消耗惰性(和无限)集合中的任何额外值。
我知道有 reduced
函数可以终止这样一个无限的东西,但我很好奇为什么在第二个版本中(range
没有 arg)它不会终止缩减,因为它达到150?
user=> (reduce (fn [a v] (if (< a 100) (+ a v) a)) (range 2000))
105
user=> (reduce (fn [a v] (if (< a 100) (+ a v) a)) (range))
因为,reduce 将函数应用于序列 (range) 中的每个元素,因此 (range) 完全实现了。
(range)
产生无限序列,
(fn [a v] (if (< a 100) (+ a v) a))
不会停止循环,它会应用于每个元素。
在 REPL 处执行
(reduce (fn [a v] (if (< a 100) (+ a v) a)) (range))
意味着我们很早就想获取并打印结果,因此 REPL 挂起。
正如你提到的,对于那些后来出现的人,谷歌搜索减少了。 reducing 函数确实有能力明确地声明归约的最终答案,并保证不会通过返回调用 (reduced the-final-answer)
user> (reduce (fn [a v]
(if (< a 100)
(+ a v)
(reduced a)))
(range))
105
在这种情况下,当新收集的结果超过 100 时,下一次迭代将停止减少,而不是将其值贡献给答案。这确实消耗了输入流中未包含在结果中的一个额外值。
user> (reduce (fn [a v]
(let [res (+ a v)]
(if (< res 100)
res
(reduced res))))
(range))
105
这会在达到阈值后立即完成缩减,并且不会消耗惰性(和无限)集合中的任何额外值。