user4813927
user4813927

Reputation:

Clojure reduced function

I know there is the reduced function to terminate such an infinite thing, but i am curious why in the second version (with range without arg) it doesn't terminate the reduction as it reaches 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))

Upvotes: 2

Views: 149

Answers (2)

Arthur Ulfeldt
Arthur Ulfeldt

Reputation: 91554

As you mention, and for those who come along later googling for reduced. The reducing function does have a the ability to declare the final answer of the reduction explicitly with the guarantee that no further input will be consumed by returning the result of calling (reduced the-final-answer)

user> (reduce (fn [a v] 
                (if (< a 100) 
                  (+ a v) 
                  (reduced a))) 
               (range))
105

In this case when the new collected result passes 100 the next iteration will stop the reduction rather than contribute it's value to the answer. This does consume one extra value from the input stream that is not included in the result.

user> (reduce (fn [a v]
                (let [res (+ a v)]
                  (if (< res 100)
                    res
                    (reduced res))))
              (range))
105

This finishes the reduction as soon as threshold is met and does not consume any extra values from the lazy (and infinite) collection.

Upvotes: 4

Nicolas Modrzyk
Nicolas Modrzyk

Reputation: 14197

Because, reduce applies the function to every element in the sequence (range), thus (range) is fully realized.

 (range) 

produces an infinite sequence, and

 (fn [a v] (if (< a 100) (+ a v) a))

doesn't stop the loop, it is being applied to every element.

Executed at the REPL

 (reduce (fn [a v] (if (< a 100) (+ a v) a)) (range))

means we eargly wants to get and print the result, therefore the REPL hangs.

Upvotes: 4

Related Questions