Last active
January 28, 2022 21:00
-
-
Save IGJoshua/0388076fcc9253575ea7b20f4522fa4d to your computer and use it in GitHub Desktop.
Reloadable function vars
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(require '[clojure.spec.alpha :as s]) | |
(s/def ::defreloadable-args | |
(s/cat :name simple-symbol? | |
:doc (s/? string?) | |
:attr-map (s/? map?) | |
:fn-tails (s/+ any?))) | |
(defmacro defreloadable | |
"Defines a new function as [[defn]], but old references will refer to new versions when reloaded. | |
This will construct a phantom var that's used for the lookup, so calls to | |
functions defined with this macro will have an additional layer of | |
indirection as compared to normal functions. This should also work in | |
production environments compiled with direct linking turned on. | |
I do not recommend using this macro, but it can be useful for beginners | |
who are learning how to write webservers or other persistent applications | |
and don't want to worry about having a bad reloadability experience. | |
Instead of using this, I recommend learning about Clojure's evaluation | |
model, which will allow you to have the same benefits as using this | |
macro, but without any magic." | |
[& args] | |
(let [args (s/conform ::defreloadable-args args)] | |
`(let [v# (or (when-let [fn# (binding [*ns* ~*ns*] | |
(resolve '~(:name args)))] | |
(-> (meta fn#) ::impl)) | |
(with-local-vars [v# nil] v#))] | |
(alter-var-root v# (constantly (fn ~@(:fn-tails args)))) | |
(doto (def ~(:name args) (fn [~'& args#] (apply @v# args#))) | |
(alter-meta! merge (assoc (merge {:doc ~(:doc args)} | |
~(:attr-map args)) | |
::impl v#)))))) | |
(s/fdef defreloadable | |
:args ::defreloadable-args) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Consider this to be under the MIT license, feel free to copy and use in any way you like.