diff --git a/src/clj/com/rpl/specter.cljx b/src/clj/com/rpl/specter.cljx index 37dfc23..357f57b 100644 --- a/src/clj/com/rpl/specter.cljx +++ b/src/clj/com/rpl/specter.cljx @@ -3,20 +3,20 @@ [com.rpl.specter.macros :refer [pathed-collector - variable-pathed-path - fixed-pathed-path + variable-pathed-nav + fixed-pathed-nav defcollector - defpath + defnav defpathedfn ]] ) - (:use [com.rpl.specter.protocols :only [StructurePath]] + (:use [com.rpl.specter.protocols :only [Navigator]] #+clj [com.rpl.specter.macros :only [pathed-collector - variable-pathed-path - fixed-pathed-path + variable-pathed-nav + fixed-pathed-nav defcollector - defpath + defnav defpathedfn]] ) (:require [com.rpl.specter.impl :as i] @@ -119,7 +119,7 @@ (defn replace-in "Similar to transform, except returns a pair of [transformed-structure sequence-of-user-ret]. - The transform-fn in this case is expected to return [ret user-ret]. ret is + The transform-fn in this case is expected to return [ret user-ret]. ret is what's used to transform the data structure, while user-ret will be added to the user-ret sequence in the final return. replace-in is useful for situations where you need to know the specific values of what was transformed in the data structure." @@ -151,7 +151,7 @@ ;; Built-in pathing and context operations -(defpath +(defnav ^{:doc "Stops navigation at this point. For selection returns nothing and for transformation returns the structure unchanged"} STOP @@ -162,7 +162,7 @@ structure )) -(defpath +(defnav ^{:doc "Stays navigated at the current point. Essentially a no-op navigator."} STAY [] @@ -171,15 +171,15 @@ (transform* [this structure next-fn] (next-fn structure))) -(def ALL (comp-paths (i/->AllStructurePath))) +(def ALL (comp-paths (i/->AllNavigator))) (def VAL (i/->ValCollect)) -(def LAST (comp-paths (i/->PosStructurePath last i/set-last))) +(def LAST (comp-paths (i/->PosNavigator last i/set-last))) -(def FIRST (comp-paths (i/->PosStructurePath first i/set-first))) +(def FIRST (comp-paths (i/->PosNavigator first i/set-first))) -(defpath +(defnav ^{:doc "Uses start-fn and end-fn to determine the bounds of the subsequence to select when navigating. Each function takes in the structure as input."} srange-dynamic @@ -190,7 +190,7 @@ (i/srange-transform structure (start-fn structure) (end-fn structure) next-fn) )) -(defpath +(defnav ^{:doc "Navigates to the subsequence bound by the indexes start (inclusive) and end (exclusive)"} srange @@ -205,7 +205,7 @@ (def END (srange-dynamic count count)) -(defpath +(defnav ^{:doc "Navigates to the specified subset (by taking an intersection). In a transform, that subset in the original set is changed to the new value of the subset."} @@ -221,7 +221,7 @@ (set/union newset)) ))) -(defpath +(defnav ^{:doc "Navigates to the specified submap (using select-keys). In a transform, that submap in the original map is changed to the new value of the submap."} @@ -236,7 +236,7 @@ (merge (reduce dissoc structure m-keys) newmap)))) -(defpath +(defnav walker [afn] (select* [this structure next-fn] @@ -244,7 +244,7 @@ (transform* [this structure next-fn] (i/walk-until afn next-fn structure))) -(defpath +(defnav codewalker [afn] (select* [this structure next-fn] @@ -260,7 +260,7 @@ children in the same order when executed on \"select\" and then \"transform\"." [& path] - (fixed-pathed-path [late path] + (fixed-pathed-nav [late path] (select* [this structure next-fn] (next-fn (compiled-select late structure))) (transform* [this structure next-fn] @@ -273,7 +273,7 @@ next-val)) structure))))) -(defpath +(defnav ^{:doc "Navigates to the specified key, navigating to nil if it does not exist."} keypath [key] @@ -283,7 +283,7 @@ (assoc structure key (next-fn (get structure key))) )) -(defpath +(defnav ^{:doc "Navigates to the key only if it exists in the map."} must [k] @@ -296,7 +296,7 @@ structure ))) -(defpath +(defnav ^{:doc "Navigates to result of running `afn` on the currently navigated value."} view [afn] @@ -306,14 +306,14 @@ (next-fn (afn structure)) )) -(defpath parser [parse-fn unparse-fn] +(defnav parser [parse-fn unparse-fn] (select* [this structure next-fn] (next-fn (parse-fn structure))) (transform* [this structure next-fn] (unparse-fn (next-fn (parse-fn structure))) )) -(defpath +(defnav ^{:doc "Navigates to atom value."} ATOM [] @@ -333,7 +333,7 @@ will be parameterized in the order of which the parameterized navigators were declared." [& path] - (fixed-pathed-path [late path] + (fixed-pathed-nav [late path] (select* [this structure next-fn] (i/filter-select #(i/selected?* late %) @@ -346,7 +346,7 @@ next-fn)))) (defpathedfn not-selected? [& path] - (fixed-pathed-path [late path] + (fixed-pathed-nav [late path] (select* [this structure next-fn] (i/filter-select #(i/not-selected?* late %) @@ -377,14 +377,14 @@ will be parameterized in the order of which the parameterized navigators were declared." [path update-fn] - (fixed-pathed-path [late path] + (fixed-pathed-nav [late path] (select* [this structure next-fn] (next-fn (compiled-transform late update-fn structure))) (transform* [this structure next-fn] (next-fn (compiled-transform late update-fn structure))))) (extend-type #+clj clojure.lang.Keyword #+cljs cljs.core/Keyword - StructurePath + Navigator (select* [kw structure next-fn] (next-fn (get structure kw))) (transform* [kw structure next-fn] @@ -392,14 +392,14 @@ )) (extend-type #+clj clojure.lang.AFn #+cljs function - StructurePath + Navigator (select* [afn structure next-fn] (i/filter-select afn structure next-fn)) (transform* [afn structure next-fn] (i/filter-transform afn structure next-fn))) (extend-type #+clj clojure.lang.PersistentHashSet #+cljs cljs.core/PersistentHashSet - StructurePath + Navigator (select* [aset structure next-fn] (i/filter-select aset structure next-fn)) (transform* [aset structure next-fn] @@ -412,7 +412,7 @@ i/pred* ) -(defpath +(defnav ^{:doc "Navigates to the provided val if the structure is nil. Otherwise it stays navigated at the structure."} nil->val @@ -462,7 +462,7 @@ will be parameterized in the order of which the parameterized navigators were declared." [& conds] - (variable-pathed-path [compiled-paths conds] + (variable-pathed-nav [compiled-paths conds] (select* [this structure next-fn] (if-let [selector (i/retrieve-cond-selector compiled-paths structure)] (->> (compiled-select selector structure) @@ -484,7 +484,7 @@ "A path that branches on multiple paths. For updates, applies updates to the paths in order." [& paths] - (variable-pathed-path [compiled-paths paths] + (variable-pathed-nav [compiled-paths paths] (select* [this structure next-fn] (->> compiled-paths (mapcat #(compiled-select % structure)) diff --git a/src/clj/com/rpl/specter/impl.cljx b/src/clj/com/rpl/specter/impl.cljx index 1b1538b..a0911f3 100644 --- a/src/clj/com/rpl/specter/impl.cljx +++ b/src/clj/com/rpl/specter/impl.cljx @@ -67,9 +67,9 @@ (apply transform-fn (conj vals structure)))))) )) -(def StructurePathExecutor +(def LeanPathExecutor (->ExecutorFunctions - :spath + :leanpath (fn [params params-idx selector structure] (selector structure (fn [structure] [structure]))) (fn [params params-idx transformer transform-fn structure] @@ -158,8 +158,8 @@ (defn structure-path-impl [this] (if (fn? this) ;;TODO: this isn't kosher, it uses knowledge of internals of protocols - (-> p/StructurePath :impls (get clojure.lang.AFn)) - (find-protocol-impl! p/StructurePath this))) + (-> p/Navigator :impls (get clojure.lang.AFn)) + (find-protocol-impl! p/Navigator this))) #+clj (defn collector-impl [this] @@ -168,8 +168,8 @@ #+cljs (defn structure-path-impl [obj] - {:select* (mk-optimized-invocation p/StructurePath obj select* 2) - :transform* (mk-optimized-invocation p/StructurePath obj transform* 2) + {:select* (mk-optimized-invocation p/Navigator obj select* 2) + :transform* (mk-optimized-invocation p/Navigator obj transform* 2) }) #+cljs @@ -196,7 +196,7 @@ transformer (:transform* pimpl)] (no-params-compiled-path (->TransformFunctions - StructurePathExecutor + LeanPathExecutor (fn [structure next-fn] (selector this structure next-fn)) (fn [structure next-fn] @@ -217,7 +217,7 @@ ))) (defn structure-path? [obj] - (or (fn? obj) (satisfies? p/StructurePath obj))) + (or (fn? obj) (satisfies? p/Navigator obj))) (defprotocol CoercePath (coerce-path [this])) @@ -528,10 +528,10 @@ (into empty-structure (map #(next-fn %)) structure) ))) -(deftype AllStructurePath []) +(deftype AllNavigator []) -(extend-protocol p/StructurePath - AllStructurePath +(extend-protocol p/Navigator + AllNavigator (select* [this structure next-fn] (all-select structure next-fn)) (transform* [this structure next-fn] @@ -544,10 +544,10 @@ (collect-val [this structure] structure)) -(deftype PosStructurePath [getter setter]) +(deftype PosNavigator [getter setter]) -(extend-protocol p/StructurePath - PosStructurePath +(extend-protocol p/Navigator + PosNavigator (select* [this structure next-fn] (if-not (empty? structure) (next-fn ((.-getter this) structure)))) @@ -570,7 +570,7 @@ res ))) -(extend-protocol p/StructurePath +(extend-protocol p/Navigator nil (select* [this structure next-fn] (next-fn structure)) @@ -724,8 +724,7 @@ (instance? VarUse p) (let [v (:var p) vv (var-get v)] - (cond (-> v meta :dynamic) - (magic-fail! "Var " (:sym p) " is dynamic") + (cond (-> v meta :dynamic) (magic-fail! "Var " (:sym p) " is dynamic") (valid-navigator? vv) vv :else (magic-fail! "Var " (:sym p) " is not a navigator") )) diff --git a/src/clj/com/rpl/specter/macros.clj b/src/clj/com/rpl/specter/macros.clj index 27607e6..fc2206e 100644 --- a/src/clj/com/rpl/specter/macros.clj +++ b/src/clj/com/rpl/specter/macros.clj @@ -19,14 +19,14 @@ (def PARAMS-SYM (vary-meta (gensym "params") assoc :tag 'objects)) (def PARAMS-IDX-SYM (gensym "params-idx")) -(defn paramspath* [bindings num-params [impl1 impl2]] +(defn paramsnav* [bindings num-params [impl1 impl2]] (let [[[[_ s-structure-sym s-next-fn-sym] & select-body] [[_ t-structure-sym t-next-fn-sym] & transform-body]] (determine-params-impls impl1 impl2)] (if (= 0 num-params) `(i/no-params-compiled-path (i/->TransformFunctions - i/StructurePathExecutor + i/LeanPathExecutor (fn [~s-structure-sym ~s-next-fn-sym] ~@select-body) (fn [~t-structure-sym ~t-next-fn-sym] @@ -76,7 +76,7 @@ ~num-params ))) -(defn pathed-path* [builder paths-seq latefns-sym pre-bindings post-bindings impls] +(defn pathed-nav* [builder paths-seq latefns-sym pre-bindings post-bindings impls] (let [num-params-sym (gensym "num-params")] `(let [paths# (map i/comp-paths* ~paths-seq) needed-params# (map i/num-needed-params paths#) @@ -114,19 +114,19 @@ (apply concat))) -(defmacro path - "Defines a StructurePath with late bound parameters. This path can be precompiled - with other selectors without knowing the parameters. When precompiled with other - selectors, the resulting selector takes in parameters for all selectors in the path +(defmacro nav + "Defines a navigator with late bound parameters. This navigator can be precompiled + with other navigators without knowing the parameters. When precompiled with other + navigators, the resulting path takes in parameters for all navigators in the path that needed parameters (in the order in which they were declared)." [params impl1 impl2] (let [num-params (count params) retrieve-params (make-param-retrievers params)] - (paramspath* retrieve-params num-params [impl1 impl2]) + (paramsnav* retrieve-params num-params [impl1 impl2]) )) (defmacro paramsfn [params [structure-sym] & impl] - `(path ~params + `(nav ~params (~'select* [this# structure# next-fn#] (let [afn# (fn [~structure-sym] ~@impl)] (i/filter-select afn# structure# next-fn#) @@ -148,16 +148,16 @@ (paramscollector* retrieve-params num-params impl) )) -(defmacro defpath [name & body] - `(def ~name (path ~@body))) +(defmacro defnav [name & body] + `(def ~name (nav ~@body))) (defmacro defcollector [name & body] `(def ~name (paramscollector ~@body))) -(defmacro fixed-pathed-path - "This helper is used to define selectors that take in a fixed number of other selector - paths as input. Those selector paths may require late-bound params, so this helper - will create a parameterized selector if that is the case. If no late-bound params +(defmacro fixed-pathed-nav + "This helper is used to define navigators that take in a fixed number of other + paths as input. Those paths may require late-bound params, so this helper + will create a parameterized navigator if that is the case. If no late-bound params are required, then the result is executable." [bindings impl1 impl2] (let [bindings (partition 2 bindings) @@ -165,23 +165,23 @@ names (mapv first bindings) latefns-sym (gensym "latefns") latefn-syms (vec (gensyms (count paths)))] - (pathed-path* - paramspath* + (pathed-nav* + paramsnav* paths latefns-sym [latefn-syms latefns-sym] (mapcat (fn [n l] [n `(~l ~PARAMS-SYM ~PARAMS-IDX-SYM)]) names latefn-syms) [impl1 impl2]))) -(defmacro variable-pathed-path - "This helper is used to define selectors that take in a variable number of other selector - paths as input. Those selector paths may require late-bound params, so this helper - will create a parameterized selector if that is the case. If no late-bound params +(defmacro variable-pathed-nav + "This helper is used to define navigators that take in a variable number of other + paths as input. Those paths may require late-bound params, so this helper + will create a parameterized navigator if that is the case. If no late-bound params are required, then the result is executable." [[latepaths-seq-sym paths-seq] impl1 impl2] (let [latefns-sym (gensym "latefns")] - (pathed-path* - paramspath* + (pathed-nav* + paramsnav* paths-seq latefns-sym [] @@ -198,7 +198,7 @@ [[name path] impl] (let [latefns-sym (gensym "latefns") latefn (gensym "latefn")] - (pathed-path* + (pathed-nav* paramscollector* [path] latefns-sym diff --git a/src/clj/com/rpl/specter/protocols.cljx b/src/clj/com/rpl/specter/protocols.cljx index d742b98..b448a9d 100644 --- a/src/clj/com/rpl/specter/protocols.cljx +++ b/src/clj/com/rpl/specter/protocols.cljx @@ -1,6 +1,6 @@ (ns com.rpl.specter.protocols) -(defprotocol StructurePath +(defprotocol Navigator (select* [this structure next-fn]) (transform* [this structure next-fn])) diff --git a/src/clj/com/rpl/specter/zipper.cljx b/src/clj/com/rpl/specter/zipper.cljx index c263eec..4b91584 100644 --- a/src/clj/com/rpl/specter/zipper.cljx +++ b/src/clj/com/rpl/specter/zipper.cljx @@ -1,14 +1,14 @@ (ns com.rpl.specter.zipper #+cljs (:require-macros [com.rpl.specter.macros - :refer [defpath path declarepath providepath]]) + :refer [defnav nav declarepath providepath]]) #+clj (:use - [com.rpl.specter.macros :only [defpath path declarepath providepath]]) + [com.rpl.specter.macros :only [defnav nav declarepath providepath]]) (:require [com.rpl.specter :as s] [clojure.zip :as zip])) -(defpath zipper [constructor] +(defnav zipper [constructor] (select* [this structure next-fn] (next-fn (constructor structure))) (transform* [this structure next-fn] @@ -30,14 +30,14 @@ s/STAY))) -(defn- mk-zip-nav [nav] - (path [] +(defn- mk-zip-nav [znav] + (nav [] (select* [this structure next-fn] - (let [ret (nav structure)] + (let [ret (znav structure)] (if ret (next-fn ret)) )) (transform* [this structure next-fn] - (let [ret (nav structure)] + (let [ret (znav structure)] (if ret (next-fn ret) structure) )))) @@ -76,7 +76,7 @@ inserts) )) -(defpath ^{:doc "Navigate to the empty subsequence directly to the +(defnav ^{:doc "Navigate to the empty subsequence directly to the right of this element."} INNER-RIGHT [] (select* [this structure next-fn] @@ -85,7 +85,7 @@ (inner-insert structure next-fn zip/insert-right zip/right zip/left) )) -(defpath ^{:doc "Navigate to the empty subsequence directly to the +(defnav ^{:doc "Navigate to the empty subsequence directly to the left of this element."} INNER-LEFT [] (select* [this structure next-fn] @@ -94,7 +94,7 @@ (inner-insert structure next-fn zip/insert-left identity nil) )) -(defpath NODE [] +(defnav NODE [] (select* [this structure next-fn] (next-fn (zip/node structure)) ) @@ -102,7 +102,7 @@ (zip/edit structure next-fn) )) -(defpath ^{:doc "Navigate to the subsequence containing only +(defnav ^{:doc "Navigate to the subsequence containing only the node currently pointed to. This works just like srange and can be used to remove elements from the structure"} diff --git a/test/com/rpl/specter/core_test.cljx b/test/com/rpl/specter/core_test.cljx index 88ee545..08de3dd 100644 --- a/test/com/rpl/specter/core_test.cljx +++ b/test/com/rpl/specter/core_test.cljx @@ -4,15 +4,15 @@ [cljs.test.check.cljs-test :refer [defspec]] [com.rpl.specter.cljs-test-helpers :refer [for-all+]] [com.rpl.specter.macros - :refer [paramsfn defprotocolpath defpath extend-protocolpath - declarepath providepath]]) + :refer [paramsfn defprotocolpath defnav extend-protocolpath + nav declarepath providepath]]) (:use #+clj [clojure.test :only [deftest is]] #+clj [clojure.test.check.clojure-test :only [defspec]] #+clj [com.rpl.specter.test-helpers :only [for-all+]] #+clj [com.rpl.specter.macros - :only [paramsfn defprotocolpath defpath extend-protocolpath - declarepath providepath]] + :only [paramsfn defprotocolpath defnav extend-protocolpath + nav declarepath providepath]] ) @@ -603,8 +603,8 @@ val (gen/elements (range 10)) op (gen/elements [inc dec]) comparator (gen/elements [= > <])] - (let [path (s/comp-paths s/ALL (paramsfn [p] [v] (comparator v p)))] - (= (s/transform (path val) op v) + (let [cpath (s/comp-paths s/ALL (paramsfn [p] [v] (comparator v p)))] + (= (s/transform (cpath val) op v) (s/transform [s/ALL #(comparator % val)] op v))) ))