Search code examples
clojurereduce

clojure reduced not terminating reduce function


In the clojure documentation it says:

Usage: (reduced x)

Wraps x in a way such that a reduce will terminate with the value x

I am trying to return from a reduce function with a boolean and a vector values.

(def bp (reduce (fn [[balanced stack] singlenum]
    (def stack2 (conj stack singlenum))
    (println stack2)
    (if (= 2 singlenum)
      (reduced [false stack2])
    )
    [balanced stack2]
  )
  [true (vector)] [1 2 3 4]
))

bp evaluates as [true [1 2 3 4]], I was expecting [false [1 2]]. The reduced did not terminate the reduce function. I was attempting to terminate the reduce function with a specific values.


Solution

  • You have the correct logic there. I just revised your usage of if and def.

    1. if - I moved [balanced stack2] to the else part. Otherwise reduced will never be detected.
    2. def - the def inside fn should be replaced with let
    (def bp (reduce (fn [[balanced stack] singlenum]
                      (let [stack2 (conj stack singlenum)]
                           (println stack2)
                           (if (= 2 singlenum)
                             (reduced [false stack2])
                             [balanced stack2])))
                    [true (vector)]
                    [1 2 3 4]))
    
    | | | | | stack=> []
    | | | | | singlenum=> 1
    | | | | (conj stack singlenum)=> [1]
    | | | | stack2=> [1]
    [1]
    | | | (println stack2)=> nil
    | | | | | singlenum=> 1
    | | | | (= 2 singlenum)=> false
    | | | | | balanced=> true
    | | | | | stack2=> [1]
    | | | (if (= 2 singlenum) (reduced #) [balanced stack2])=> [true [1]]
    | | (let [stack2 #] (println stack2) (if # # #))=> [true [1]]
    | | | | | stack=> [1]
    | | | | | singlenum=> 2
    | | | | (conj stack singlenum)=> [1 2]
    | | | | stack2=> [1 2]
    [1 2]
    | | | (println stack2)=> nil
    | | | | | singlenum=> 2
    | | | | (= 2 singlenum)=> true
    | | | | | | stack2=> [1 2]
    | | | | (reduced [false stack2])=> #reduced[{:status :ready, :val [false [1 2]]} 0x5fbdbb78]
    | | | (if (= 2 singlenum) (reduced #) [balanced stack2])=> #reduced[{:status :ready, :val [false [1 2]]} 0x5fbdbb78]
    | | (let [stack2 #] (println stack2) (if # # #))=> #reduced[{:status :ready, :val [false [1 2]]} 0x5fbdbb78]
    (reduce (fn # #) [true #] [1 2 3 4])=> [false [1 2]]