Skip to content

Instantly share code, notes, and snippets.

Created August 30, 2021 08:38
What would you like to do?

This example illustrates an intersting side effect of Clojure's lazy sequences when used in re-frame subscriptions. The behaviour described below takes place only on initial subscribe call

(reg-sub :test/x-2
  (constantly [])
  (fn [_ _]
    (prn "evaluating body of " :test/x-2)
    (map #(do (prn "evaluating lazy seq returned from " :test/x-2) (inc %)) (range 3))))

(reg-sub :test/x-1
  :<- [:test/x-2]
  (fn [x2 _]
    (prn "evaluating body of " :test/x-1)
    (map #(do (prn "evaluating lazy seq returned from " :test/x-1) (inc %)) x2)))

(defn component []
  (let [x @(subscribe [:test/x-1])]
    (prn "printing the value in Reagent componen now")
    (prn x)))

Printing order

"evaluating body of " :test/x-2
"evaluating body of " :test/x-1
"printing the value in Reagent componen now"
"evaluating lazy seq returned from " :test/x-2
"evaluating lazy seq returned from " :test/x-1
(2 3 4)

What happens here?

Evaluation of a lazy seq, returned from a subscription, is being deferred until a point where the resulting value is realized/evaluated

What are the consequences?

Even though lazy seq caches its compued value, so it's not evaluated again and again, deferred evaluation makes debugging harder, since the code defined in subscription body is evaluated in component tree.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment