Skip to content

Instantly share code, notes, and snippets.

@bhb
Created March 23, 2018 19:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bhb/128bf97619e83541a8adda7094bc370d to your computer and use it in GitHub Desktop.
Save bhb/128bf97619e83541a8adda7094bc370d to your computer and use it in GitHub Desktop.
Conform/unform to rewrite function bodies
(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