diff --git a/src/clj/com/rpl/specter.cljc b/src/clj/com/rpl/specter.cljc index 50eb651..c5fbe73 100644 --- a/src/clj/com/rpl/specter.cljc +++ b/src/clj/com/rpl/specter.cljc @@ -359,38 +359,38 @@ next-val)) structure))))) -(defnav +(defrichnav ^{:doc "Navigates to the specified key, navigating to nil if it does not exist."} keypath [key] - (select* [this structure next-fn] - (next-fn (get structure key))) - (transform* [this structure next-fn] - (assoc structure key (next-fn (get structure key))))) + (select* [this vals structure next-fn] + (next-fn vals (get structure key))) + (transform* [this vals structure next-fn] + (assoc structure key (next-fn vals (get structure key))))) -(defnav +(defrichnav ^{:doc "Navigates to the key only if it exists in the map."} must [k] - (select* [this structure next-fn] + (select* [this vals structure next-fn] (if (contains? structure k) - (next-fn (get structure k)) + (next-fn vals (get structure k)) NONE)) - (transform* [this structure next-fn] + (transform* [this vals structure next-fn] (if (contains? structure k) - (assoc structure k (next-fn (get structure k))) + (assoc structure k (next-fn vals (get structure k))) structure))) -(defnav +(defrichnav ^{:doc "Navigates to result of running `afn` on the currently navigated value."} view [afn] - (select* [this structure next-fn] - (next-fn (afn structure))) - (transform* [this structure next-fn] - (next-fn (afn structure)))) + (select* [this vals structure next-fn] + (next-fn vals (afn structure))) + (transform* [this vals structure next-fn] + (next-fn vals (afn structure)))) (defnav diff --git a/src/clj/com/rpl/specter/impl.cljc b/src/clj/com/rpl/specter/impl.cljc index 0e4465a..4eb0598 100644 --- a/src/clj/com/rpl/specter/impl.cljc +++ b/src/clj/com/rpl/specter/impl.cljc @@ -583,7 +583,7 @@ (defn dynamic-var? [v] - (-> v meta :dynamic not)) + (-> v meta :dynamic)) ;; don't do coerce-nav here... save that for resolve-magic-code (defn- magic-precompilation* [o] @@ -643,6 +643,19 @@ :else o)) +(defn resolve-dynamic-fn-arg-code [o] + (cond (instance? DynamicFunction o) + (let [op (resolve-dynamic-fn-arg-code (:op o)) + params (map resolve-dynamic-fn-arg-code (:params o))] + `(~op ~@params)) + + (instance? DynamicVal o) + (:code o) + + :else + o)) + + (defn resolve-magic-code [o] (cond (instance? DynamicPath o) @@ -655,7 +668,7 @@ rich-nav? resolved (fn [s] [(comp-paths* s)]))] - (if (and (= 1 (count combined)) (rich-nav? (first combined))) + (if (= 1 (count combined)) (first combined) `(comp-navs ~@combined)))) (resolve-magic-code path))) @@ -675,7 +688,8 @@ params (map resolve-dynamic-fn-arg (:params o))] (if (all-static? (conj params op)) (coerce-nav (apply op params)) - `(coerce-nav (~(resolve-magic-code op) ~@(map resolve-magic-code params))))) + `(coerce-nav (~(resolve-dynamic-fn-arg-code op) + ~@(map resolve-dynamic-fn-arg-code params))))) :else (coerce-nav o))) @@ -683,11 +697,13 @@ (defn magic-precompilation [path ns-str used-locals] (let [path (magic-precompilation* path) +; _ (println "magic-precompilation*" path) ns (find-ns (symbol ns-str)) maker (binding [*ns* ns] (eval+ - `(fn [~@used-locals] - ~(resolve-magic-code (->DynamicPath path)))))] +; (spy + `(fn [~@used-locals] + ~(resolve-magic-code (->DynamicPath path)))))] (if (static-path? path) (->CachedPathInfo false (maker)) (->CachedPathInfo true maker))))