diff --git a/src/clj/com/rpl/specter.cljc b/src/clj/com/rpl/specter.cljc index 60642ab..40b586a 100644 --- a/src/clj/com/rpl/specter.cljc +++ b/src/clj/com/rpl/specter.cljc @@ -825,16 +825,16 @@ walker [afn] (select* [this structure next-fn] - (n/walk-select afn next-fn structure)) + (i/walk-select afn next-fn structure)) (transform* [this structure next-fn] - (n/walk-until afn next-fn structure))) + (i/walk-until afn next-fn structure))) (defnav ^{:doc "Like `walker` but maintains metadata of any forms traversed."} codewalker [afn] (select* [this structure next-fn] - (n/walk-select afn next-fn structure)) + (i/walk-select afn next-fn structure)) (transform* [this structure next-fn] (i/codewalk-until afn next-fn structure))) diff --git a/src/clj/com/rpl/specter/impl.cljc b/src/clj/com/rpl/specter/impl.cljc index ab2c8e5..b599b72 100644 --- a/src/clj/com/rpl/specter/impl.cljc +++ b/src/clj/com/rpl/specter/impl.cljc @@ -572,6 +572,25 @@ (with-meta ret (meta structure)) ret)))) +(defn walk-select [pred continue-fn structure] + (let [ret (mutable-cell NONE) + walker (fn this [structure] + (if (pred structure) + (let [r (continue-fn structure)] + (if-not (identical? r NONE) + (set-cell! ret r)) + r) + + (walk/walk this identity structure)))] + + (walker structure) + (get-cell ret))) + +(defn walk-until [pred on-match-fn structure] + (if (pred structure) + (on-match-fn structure) + (walk/walk (partial walk-until pred on-match-fn) identity structure))) + #?(:clj (do @@ -645,7 +664,7 @@ (-> o meta :direct-nav)) (defn all-static? [params] - (every? (complement dynamic-param?) params)) + (identical? NONE (walk-select dynamic-param? identity params))) (defn late-resolved-fn [afn] (fn [& args] @@ -654,11 +673,14 @@ (->DynamicFunction afn args) ))) +(defn preserve-map [afn o] + (if (or (list? o) (seq? o)) + (map afn o) + (into (empty o) (map afn o)))) + (defn- magic-precompilation* [o] (cond (sequential? o) - (if (or (list? o) (seq? o)) - (map magic-precompilation* o) - (into (empty o) (map magic-precompilation* o))) + (preserve-map magic-precompilation* o) (instance? VarUse o) (if (dynamic-var? (:var o)) @@ -694,17 +716,15 @@ ([o] (static-combine o true)) ([o nav-pos?] (cond (sequential? o) - (do - (if-not nav-pos? - ;; should never happen... - (throw-illegal "Cannot statically combine sequential when not in nav pos")) + (if nav-pos? (let [res (continuous-subseqs-transform* rich-nav? (doall (map static-combine (flatten o))) (fn [s] [(comp-paths* s)]))] (if (= 1 (count res)) (first res) - res))) + res)) + (preserve-map #(static-combine % false) o)) (instance? DynamicFunction o) (->DynamicFunction @@ -800,7 +820,12 @@ (resolve-nav-code o possible-params) :else - (static-val-code o))) + ;; handle dynamic params nested inside data structures + ;; e.g. (terminal-val [v]) + (if (identical? NONE (walk-select dynamic-param? identity o)) + (static-val-code o) + (resolve-arg-code (->DynamicVal (walk-until dynamic-param? :code o)) possible-params) + ))) (defn resolve-nav-code [o possible-params] (cond diff --git a/src/clj/com/rpl/specter/navs.cljc b/src/clj/com/rpl/specter/navs.cljc index 90b9a77..8fffc64 100644 --- a/src/clj/com/rpl/specter/navs.cljc +++ b/src/clj/com/rpl/specter/navs.cljc @@ -8,7 +8,6 @@ (:use #?(:clj [com.rpl.specter.macros :only [defnav defrichnav]]) #?(:clj [com.rpl.specter.util-macros :only [doseqres]])) (:require [com.rpl.specter.impl :as i] - [clojure.walk :as walk] #?(:clj [clojure.core.reducers :as r]))) @@ -22,19 +21,6 @@ [compiled-path vals structure] (not (not-selected?* compiled-path vals structure))) -(defn walk-select [pred continue-fn structure] - (let [ret (i/mutable-cell i/NONE) - walker (fn this [structure] - (if (pred structure) - (let [r (continue-fn structure)] - (if-not (identical? r i/NONE) - (i/set-cell! ret r)) - r) - - (walk/walk this identity structure)))] - - (walker structure) - (i/get-cell ret))) (defn all-select [structure next-fn] (doseqres i/NONE [e structure] @@ -592,12 +578,6 @@ (empty? s))) -(defn walk-until [pred on-match-fn structure] - (if (pred structure) - (on-match-fn structure) - (walk/walk (partial walk-until pred on-match-fn) identity structure))) - - (defn- do-keypath-transform [vals structure key next-fn] (let [newv (next-fn vals (get structure key))] (if (identical? newv i/NONE) diff --git a/test/com/rpl/specter/core_test.cljc b/test/com/rpl/specter/core_test.cljc index e9ab5d8..29382fb 100644 --- a/test/com/rpl/specter/core_test.cljc +++ b/test/com/rpl/specter/core_test.cljc @@ -1507,3 +1507,9 @@ (is (= "b" (setval s/FIRST s/NONE "ab"))) (is (= "a" (setval s/LAST s/NONE "ab"))) ) + +(deftest nested-dynamic-arg-test + (let [foo (fn [v] (multi-transform (s/terminal-val [v]) nil))] + (is (= [1] (foo 1))) + (is (= [10] (foo 10))) + ))