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

这会在达到阈值后立即完成缩减,并且不会消耗惰性(和无限)集合中的任何额外值。