Created
March 23, 2018 19:41
-
-
Save bhb/128bf97619e83541a8adda7094bc370d to your computer and use it in GitHub Desktop.
Conform/unform to rewrite function bodies
This file contains 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
(defn update-bodies | |
"Updates all function bodies in the destructured value. | |
args: | |
f - a function of two args. The first is the destructured value, the second is the body. | |
conformed-defn-args - the destructured value after conforming to :clojure.core.specs.alpha/defn-args | |
returns: a new destructured value where f has been applied to all function bodies in the | |
destructured value. | |
See http://blog.klipse.tech/clojure/2016/10/10/defn-args.html for more details on modifying | |
defn args." | |
[f conformed-defn-args] | |
(let [body-paths (case (get-in conformed-defn-args [:bs 0]) | |
:arity-1 [[:bs 1 :body 1]] | |
:arity-n (for [x (range (count (get-in conformed-defn-args [:bs 1 :bodies])))] | |
[:bs 1 :bodies x :body 1]))] | |
(reduce | |
(fn [new-conformed path] | |
(update-in new-conformed path (partial f conformed-defn-args))) | |
conformed-defn-args | |
body-paths))) | |
(defn rewrite-def [defn-args update-bodies-fn] | |
(let [old-spec (s/spec :clojure.core.specs.alpha/arg-list) | |
spec :clojure.core.specs.alpha/defn-args] | |
(try | |
(s/def :clojure.core.specs.alpha/arg-list vector?) | |
(->> defn-args | |
(s/conform spec) | |
(update-bodies update-bodies-fn) | |
(s/unform spec) | |
(cons `defn)) | |
(finally | |
(s/def :clojure.core.specs.alpha/arg-list old-spec))))) | |
(defmacro fn-traced | |
[fn-name & rest] | |
(rewrite-def (cons fn-name rest) | |
(fn [conformed body] | |
[`(dbgn | |
~@body)]))) | |
(comment | |
(macroexpand '(fn-traced foo [x y] (+ x y))) | |
;; => (def foo (clojure.core/fn ([x y] (stopwatch.core/dbgn (+ x y))))) | |
(macroexpand '(fn-traced foo | |
([x] (foo x 0)) | |
([x y] (+ x y)))) | |
;; => (def foo (clojure.core/fn ([x] (stopwatch.core/dbgn (foo x 0))) ([x y] (stopwatch.core/dbgn (+ x y))))) | |
) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment