From e571df58328f631aee5b3310088c2d6fe27690e6 Mon Sep 17 00:00:00 2001 From: Nathan Marz Date: Thu, 1 Sep 2016 16:59:40 -0400 Subject: [PATCH] add code to avoid embedding functions with metadata on them (which kills perf) --- src/clj/com/rpl/specter/impl.cljc | 19 +++++++++++++++---- src/clj/com/rpl/specter/macros.clj | 5 ++--- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/clj/com/rpl/specter/impl.cljc b/src/clj/com/rpl/specter/impl.cljc index 6ca49e5..61e5b69 100644 --- a/src/clj/com/rpl/specter/impl.cljc +++ b/src/clj/com/rpl/specter/impl.cljc @@ -603,14 +603,24 @@ (defn dynamic-var? [v] (-> v meta :dynamic)) +(defn direct-nav-obj [o] + (vary-meta o merge {:direct-nav true :original-obj o})) + (defn maybe-direct-nav [obj direct-nav?] (if direct-nav? - (vary-meta obj assoc :direct-nav true) + (direct-nav-obj obj) obj)) +(defn original-obj [o] + (let [orig (-> o meta :original-obj)] + (if orig + (recur orig) + o))) + (defn direct-nav? [o] (-> o meta :direct-nav)) + ;; don't do coerce-nav here... save that for resolve-magic-code (defn- magic-precompilation* [o] (cond (sequential? o) @@ -680,13 +690,13 @@ (cond (instance? DynamicFunction o) (let [op (resolve-dynamic-fn-arg-code (:op o)) params (map resolve-dynamic-fn-arg-code (:params o))] - `(~op ~@params)) + `(~(original-obj op) ~@params)) (instance? DynamicVal o) (:code o) :else - o)) + (original-obj o))) (defn resolve-magic-code [o] @@ -716,7 +726,8 @@ params (map resolve-dynamic-fn-arg (:params o))] (if (all-static? (conj params op)) (coerce-nav (apply op params)) - (let [code `(~(resolve-dynamic-fn-arg-code op) ~@(map resolve-dynamic-fn-arg-code params))] + (let [code `(~(-> op resolve-dynamic-fn-arg-code original-obj) + ~@(map resolve-dynamic-fn-arg-code params))] (if (direct-nav? op) code `(coerce-nav ~code))))) :else diff --git a/src/clj/com/rpl/specter/macros.clj b/src/clj/com/rpl/specter/macros.clj index 10ebc10..2b8b3bd 100644 --- a/src/clj/com/rpl/specter/macros.clj +++ b/src/clj/com/rpl/specter/macros.clj @@ -14,11 +14,10 @@ (defmacro richnav [params & impls] (if (empty? params) `(reify RichNavigator ~@impls) - `(vary-meta + `(i/direct-nav-obj (fn ~params (reify RichNavigator - ~@impls)) - assoc :direct-nav true))) + ~@impls))))) (defmacro nav [params & impls]