Thursday, October 26, 2017

Use binding as an alternative to passing state around in Clojure

Let's say we have already existing functions (referred to as inner functions) called by another function (outer function) and the inner functions needs some state data so that when exception occurs, that data can be logged. However, this requires passing state around to all these inner functions and modifying the method signature. Which is fine, but depending on the taste, it might not look elegant. There is another way where the state can be bound using binding and does not have to be passed explicitly by the caller. Example follows.
(declare ^:dynamic state)

(defn err []
; does many other things
(println state)
; .. return response

(defn process []
(binding [state 1]
(err) ; 1
(set! state 2) ; update value of state
(err))) ; 2


; output
; 1
; 2
; nil
This however is an anti-pattern as the state var is being implicit to the function, but used wisely, it is an anti-anti-pattern.