我知道有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))
答案 0 :(得分:4)
因为, reduce 将函数应用于序列(范围)中的每个元素,因此(范围)完全实现。
(range)
产生无限序列,
(fn [a v] (if (< a 100) (+ a v) a))
不会停止循环,它会应用于每个元素。
在REPL执行
(reduce (fn [a v] (if (< a 100) (+ a v) a)) (range))
意味着我们很想获得并打印结果,因此REPL会挂起。
答案 1 :(得分:4)
正如你所提到的那样,对于那些后来谷歌搜索减少的人。 reduce函数确实能够明确地声明减少的最终答案,并保证通过返回调用(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
一旦达到阈值就完成减少,并且不会消耗惰性(和无限)集合中的任何额外值。