Clojure减少了功能

时间:2015-09-25 00:02:19

标签: clojure reduce

我知道有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))

2 个答案:

答案 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

一旦达到阈值就完成减少,并且不会消耗惰性(和无限)集合中的任何额外值。