missionary

lotuc 2024-02-27T14:40:55.615139Z

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)

lotuc 2024-02-27T14:41:47.639639Z

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 push

leonoel 2024-02-27T14:54:19.004119Z

Dynamic 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

lotuc 2024-02-27T15:01:39.068259Z

Thanks!

leonoel 2024-02-27T15:02:33.879139Z

I agree the doc should warn about this

lotuc 2024-02-27T15:03:32.700209Z

Yeah, maybe warn while compiling, not crashing under runtime would be great 😂

2024-02-27T16:14:03.987479Z

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