mount

Frederik 2018-03-13T09:26:06.000356Z

I am trying to write a macro that creates a state in the ns that macro was called. I cannot get the ^:dynamic part working (compiler warnings telling me that it is not dynamic). Here is what I have:

(defmacro create-notification-listener [listener-name channel-name listener-fn]
  `(defstate ^:dynamic  ~listener-name 
    :start (create-notification-listener-conn ~channel-name ~listener-fn)
    :stop (.close ~listener-name)))
and somewhere else:
(db/create-notification-listener *job-polling-job-listener* job-entities/job-update-channel notify-monitor!)
results in:
Warning: *job-polling-job-listener* not declared dynamic and thus is not dynamically rebindable, but its name suggests otherwise. Please either indicate ^:dynamic *job-polling-job-listener* or change the name. (campaignbot/scheduler/job_polling.clj:17)

tolitius 2018-03-13T14:10:41.000714Z

@f.v.claus iff you really need this complexity.. of a macro within macro, you should use vary-meta inside the macros to add to meta, and not a reader ^:dynamic macro:

boot.user=> (defmacro foo [name] `(mount/defstate ~(vary-meta name merge {:dynamic true}) :start 42 :stop (println "stopping" ~name)))
#'boot.user/foo

boot.user=> (foo *job-polling-job-listener*)
#'boot.user/*job-polling-job-listener*

boot.user=> (mount/start #'boot.user/*job-polling-job-listener*)
{:started ["#'boot.user/*job-polling-job-listener*"]}

boot.user=> @#'boot.user/*job-polling-job-listener*
42

boot.user=> (mount/stop #'boot.user/*job-polling-job-listener*)
stopping 42
{:stopped ["#'boot.user/*job-polling-job-listener*"]}