aero
aero copied to clipboard
Consider a #aero/resolve tag
This would utilize requiring-resolve
(backported from 1.10 OR not available if not present). This would make it easier to support things like extending a protocol via metadata:
^{foo.bar/some-proto-method #aero/resolve my.project/proto-method-ext} {:foo/bar :config}
This would be assistive to projects like clip and edge which allow defining the system in Aero.
I believe I have been using something similar in the past where configuration values could be functions (or indeed protocols), with the following reader:
(defn- require-resolve
([sym]
(if-let [ns (namespace sym)]
(when (ns-exists? ns)
(let [ns (symbol ns)]
(when-not (find-ns ns)
(require ns)))
(resolve sym))
(resolve sym)))
([ns sym] (require-resolve (symbol ns sym))))
(defmethod aero/reader 'fn
[opts tag value]
(try
@(require-resolve value)
(catch Exception ex
(println "Error resolving fn config value " value)
(throw ex))))
However these days I tend to go for a small keyword->config map whenever possible:
(def ^:private m {:conf-value-a my.ns/func-a
:conf-value-b my.ns/func-b
:conf-value-c my.ns/func-c})
(defn- get-conf [kw]
;; could throw here if there is no suitable value
(get m kw))
A bit more verbose perhaps, but it works with other things like Java enums.