Hi, the following usage of dynamic binding in m/cp seems not working, did I miss anything from doc?
(require '[missionary.core :as m])
(def i_ (atom 0))
(def i (m/watch i_))
(def x)) nil f))
(def m! (m #(prn :success %) #(prn :failure %)))
;;; (m!) or (reset! i_ 1) is causing JVM to crash (jdk 21.0.2 & Clojure 1.11.1 on my laptop)Crashes with the following message
Execution error (IllegalStateException) at clojure.main/main (main.java:40).
Can't change/establish root binding of: *3 with set
Execution error (IllegalStateException) at clojure.main/main (main.java:40).
Can't change/establish root binding of: *e with set
Execution error (IllegalStateException) at clojure.main/main (main.java:40).
Pop without matching pushDynamic scope is not captured and therefore dynamic vars are discouraged. This is intentional, supporting it has two major problems : 1. in clojurescript it is not possible to capture dynamic scope because vars are not reified 2. in JVM clojure it has a performance cost which is paid even if dynamic scope is not used
Thanks!
I agree the doc should warn about this
Yeah, maybe warn while compiling, not crashing under runtime would be great 😂
Because Dynamic vars are bound in the current thread. Using them in an async/multi-threads context is usually not a good idea.
On a side note, Clojure core functions do their best to convey dynamic bindings through multi-threaded code and you may convey those bindings yourself using clojure.core functions like: push-thread-bindings, bound-fn, etc