has anyone written about using vars for the dispatch function of multimethods? it's a habit i've picked up when doing repl-driven development, but i don't remember where i read about it or when i put it together
re: the cache: I think it's this https://github.com/clojure/clojure/blob/a3fa897590f70207eea3573759739810f2b6ab6c/src/jvm/clojure/lang/MultiFn.java#L26
I recall a discussion about the expectation that the dispatch function should return a small number of discrete values (EDIT: https://ask.clojure.org/index.php/10532/memory-leak-using-the-default-method-of-a-multimethod?show=10533#a10533). Doing something like a) using identity as the dispatch fn and then b) installing defmethods for like 0->"none", 1->"one", default->"many" and c) invoking it for every integer will grow the cache (2->default, 3->default, ... MAX_INT->default).
Wow, that feels very suspicious to me tbh, and at very least something worth documenting.
Oh good. Whatever the cache's quirks, interfering with the REPL benefits of using a Var as dispatch fn is not one of them.
You don't have to use a var, you just want indirection (ab)use the compiler https://github.com/bsless/eta/blob/master/src/bsless/eta.clj#L3
that's naughty
It works 🤷♂️
Bonus points - will get inlined well by the compiler when direct linking is enabled
hygiene concerns aside (this breaks with, say, ($ a)), the other two macros are just aliases right?
Yes
Asking because I feel that I'm missing a trick:
this as you say should be good for direct linking on a few-args fn, but outside of that doesn't it just add a layer of indirection for no benefit (as the dynamism is achieved by derefing the var, i.e. the same way it'd happen with var punning)?
if you care about performance then your final artifact will be directly linked and it matters if you don't, then the added level of indirection does not matter (and the var read adds more overhead than a function call that will be inlined)
and fixed the hygiene issue
using vars as in doing something like
(defn io-dispatch [{:keys [input-type output-type]}]
[input-type output-type])
(defmulti extensible-io #'io-dispatch)
(defmethod extensible-io [:edn :json] [m] (json/write-str (:data m)))
instead of
(defmulti extensible-io io-dispatch)
if so, this definitely would have helped me recently 😅
yes! exactly
Is there a way to turn off the cache?
do you have a source for that which isn't from an llm?
If I could search the Clojure Jira... seems to me there was a bug (report) of a memory leak related to dispatch-function input values that lead to the default path.
might be worth asking in a new thread
Always regret when I don't
big same
Seems like the same rule of thumb as passing a var to httpkit/run-server to me. Otherwise, it's not interactive!