reformat code with parinfer

This commit is contained in:
Nathan Marz 2016-08-11 10:13:27 -04:00
parent 87137c633d
commit ac3f604211
18 changed files with 1281 additions and 1294 deletions

View file

@ -1,9 +1,9 @@
(def VERSION (.trim (slurp "VERSION")))
(defproject com.rpl/specter VERSION
:jvm-opts ["-XX:-OmitStackTraceInFastThrow" ; this prevents JVM from doing optimizations which can remove stack traces from NPE and other exceptions
;"-agentpath:/Applications/YourKit_Java_Profiler_2015_build_15056.app/Contents/Resources/bin/mac/libyjpagent.jnilib"
]
:jvm-opts ["-XX:-OmitStackTraceInFastThrow"] ; this prevents JVM from doing optimizations which can remove stack traces from NPE and other exceptions
;"-agentpath:/Applications/YourKit_Java_Profiler_2015_build_15056.app/Contents/Resources/bin/mac/libyjpagent.jnilib"]
:source-paths ["src/clj"]
:java-source-paths ["src/java"]
:test-paths ["test", "target/test-classes"]
@ -18,15 +18,14 @@
com.rpl.specter.transients]
:source-uri
{#"target/classes" "https://github.com/nathanmarz/specter/tree/{version}/src/clj/{classpath}x#L{line}"
#".*" "https://github.com/nathanmarz/specter/tree/{version}/src/clj/{classpath}#L{line}"
}
}
#".*" "https://github.com/nathanmarz/specter/tree/{version}/src/clj/{classpath}#L{line}"}}
:profiles {:dev {:dependencies
[[org.clojure/test.check "0.7.0"]
[org.clojure/clojure "1.7.0"]
[org.clojure/clojurescript "1.7.10"]]
}
:test {:dependencies [[org.clojure/clojure "1.7.0"]]}
}
:aliases {"deploy" ["do" "clean," "deploy" "clojars"]}
)
[org.clojure/clojurescript "1.7.10"]]}
:test {:dependencies [[org.clojure/clojure "1.7.0"]]}}
:aliases {"deploy" ["do" "clean," "deploy" "clojars"]})

View file

@ -10,8 +10,8 @@
(when-let [s (cljs.analyzer/error-message warning-type extra)]
(binding [*out* *err*]
(println "WARNING:" (cljs.analyzer/message env s))
(println "Failed to build because of warning!")
)
(println "Failed to build because of warning!"))
(System/exit 1))))]})
(cljs.repl/repl (cljs.repl.node/repl-env)

View file

@ -3,8 +3,8 @@
[com.rpl.specter macros]
[com.rpl.specter.transients]
[com.rpl.specter.impl :only [benchmark]])
(:require [clojure.walk :as walk])
)
(:require [clojure.walk :as walk]))
;; run via `lein repl` with `(load-file "scripts/benchmarks.clj")`
@ -19,8 +19,8 @@
(let [start (System/nanoTime)
_ (dotimes [_ amt] (afn))
end (System/nanoTime)]
(/ (- end start) 1000000.0)
))
(/ (- end start) 1000000.0)))
(defn avg [numbers]
(/ (reduce + numbers)
@ -41,20 +41,20 @@
(fn [afn]
(average-time-ms 8 amt-per-iter afn))
afn-map)
[[_ best-time] & _ :as sorted] (sort-by last results)
]
[[_ best-time] & _ :as sorted] (sort-by last results)]
(println "\nAvg(ms)\t\tvs best\t\tCode")
(doseq [[k t] sorted]
(println (pretty-float5 t) "\t\t" (pretty-float3 (/ t best-time 1.0)) "\t\t" k)
)))
(println (pretty-float5 t) "\t\t" (pretty-float3 (/ t best-time 1.0)) "\t\t" k))))
(defmacro run-benchmark [name amt-per-iter & exprs]
(let [afn-map (->> exprs shuffle (map (fn [e] [`(quote ~e) `(fn [] ~e)])) (into {}))]
`(do
(println "Benchmark:" ~name (str "(" ~amt-per-iter " iterations)"))
(compare-benchmark ~amt-per-iter ~afn-map)
(println "\n********************************\n")
)))
(println "\n********************************\n"))))
(let [data {:a {:b {:c 1}}}
p (comp-paths :a :b :c)]
@ -66,8 +66,8 @@
(compiled-select-any p data)
(get-in data [:a :b :c])
(-> data :a :b :c)
(select-any [(keypath :a) (keypath :b) (keypath :c)] data)
))
(select-any [(keypath :a) (keypath :b) (keypath :c)] data)))
;; because below 1.7 there is no update function
@ -85,8 +85,8 @@
(run-benchmark "update value in nested map" 500000
(update-in data [:a :b :c] inc)
(transform [:a :b :c] inc data)
(manual-transform data inc)
))
(manual-transform data inc)))
(defn map-vals-map-iterable [^clojure.lang.IMapIterable m afn]
(let [k-it (.keyIterator m)
@ -95,10 +95,10 @@
(if (.hasNext k-it)
(let [k (.next k-it)
v (.next v-it)]
(recur (assoc ret k (afn v)))
)
ret
))))
(recur (assoc ret k (afn v))))
ret))))
(defn map-vals-map-iterable-transient [^clojure.lang.IMapIterable m afn]
(persistent!
@ -108,10 +108,10 @@
(if (.hasNext k-it)
(let [k (.next k-it)
v (.next v-it)]
(recur (assoc! ret k (afn v)))
)
ret
)))))
(recur (assoc! ret k (afn v))))
ret)))))
(let [data {:a 1 :b 2 :c 3 :d 4}]
(run-benchmark "transform values of a small map" 500000
@ -124,8 +124,8 @@
(zipmap (keys data) (map inc (vals data)))
(into {} (map (fn [e] [(key e) (inc (val e))]) data))
(map-vals-map-iterable data inc)
(map-vals-map-iterable-transient data inc)
))
(map-vals-map-iterable-transient data inc)))
(let [data (->> (for [i (range 1000)] [i i]) (into {}))]
(run-benchmark "transform values of large map" 600
@ -139,23 +139,23 @@
(zipmap (keys data) (map inc (vals data)))
(into {} (map (fn [e] [(key e) (inc (val e))]) data))
(map-vals-map-iterable data inc)
(map-vals-map-iterable-transient data inc)
))
(map-vals-map-iterable-transient data inc)))
(let [data [1 2 3 4 5]]
(run-benchmark "map a function over a vector" 1000000
(vec (map inc data))
(mapv inc data)
(transform ALL inc data)
))
(transform ALL inc data)))
(let [data [1 2 3 4 5 6 7 8 9 10]]
(run-benchmark "filter a sequence" 500000
(doall (filter even? data))
(filterv even? data)
(select [ALL even?] data)
(select-any (filterer even?) data)
))
(select-any (filterer even?) data)))
(let [data [{:a 2 :b 2} {:a 1} {:a 4} {:a 6}]
xf (comp (map :a) (filter even?))]
@ -163,8 +163,8 @@
(select [ALL :a even?] data)
(->> data (mapv :a) (filter even?) doall)
(into [] (comp (map :a) (filter even?)) data)
(into [] xf data)
))
(into [] xf data)))
(let [v (vec (range 1000))]
(run-benchmark "END on large vector"
@ -191,8 +191,8 @@
(defn tree-value-transform [afn atree]
(if (vector? atree)
(mapv #(tree-value-transform afn %) atree)
(afn atree)
))
(afn atree)))
(let [data [1 2 [[3]] [4 6 [7 [8]] 10]]]
(run-benchmark "update every value in a tree (represented with vectors)"
@ -201,8 +201,8 @@
(transform [(walker number?) even?] inc data)
(transform [TreeValues even?] inc data)
(transform [TreeValuesProt even?] inc data)
(tree-value-transform (fn [e] (if (even? e) (inc e) e)) data)
))
(tree-value-transform (fn [e] (if (even? e) (inc e) e)) data)))
(let [toappend (range 1000)]
(run-benchmark "transient comparison: building up vectors"
@ -218,8 +218,8 @@
(reduce (fn [v i] (conj v i)) [] toappend)
(reduce (fn [v i] (conj! v i)) (transient []) toappend)
(reduce (fn [v i] (setval END [i] v)) [] toappend)
(reduce (fn [v i] (setval END! [i] v)) (transient []) toappend)
))
(reduce (fn [v i] (setval END! [i] v)) (transient []) toappend)))
(let [data (vec (range 1000))
tdata (transient data)
@ -280,19 +280,18 @@
(into #{} (traverse ALL data))
(persistent!
(reduce conj! (transient #{}) (traverse ALL data)))
(reduce conj #{} (traverse ALL data))
))
(reduce conj #{} (traverse ALL data))))
(defn mult-10 [v] (* 10 v))
(let [data [1 2 3 4 5 6 7 8 9]]
(run-benchmark "multi-transform vs. consecutive transforms, one shared nav" 300000
(->> data (transform [ALL even?] mult-10) (transform [ALL odd?] dec))
(multi-transform [ALL (multi-path [even? (terminal mult-10)] [odd? (terminal dec)])] data)
))
(multi-transform [ALL (multi-path [even? (terminal mult-10)] [odd? (terminal dec)])] data)))
(let [data [[1 2 3 4 :a] [5] [6 7 :b 8 9] [10 11 12 13]]]
(run-benchmark "multi-transform vs. consecutive transforms, three shared navs" 150000
(->> data (transform [ALL ALL number? even?] mult-10) (transform [ALL ALL number? odd?] dec))
(multi-transform [ALL ALL number? (multi-path [even? (terminal mult-10)] [odd? (terminal dec)])] data)
))
(multi-transform [ALL ALL number? (multi-path [even? (terminal mult-10)] [odd? (terminal dec)])] data)))

View file

@ -8,11 +8,11 @@
defnav
defpathedfn
richnav
defnavconstructor
]]
defnavconstructor]]
[com.rpl.specter.util-macros :refer
[doseqres]]
))
[doseqres]]))
(:use [com.rpl.specter.protocols :only [ImplicitNav]]
#?(:clj [com.rpl.specter.macros :only
[fixed-pathed-collector
@ -22,12 +22,12 @@
defpathedfn
richnav
defnavconstructor]])
#?(:clj [com.rpl.specter.util-macros :only [doseqres]])
)
#?(:clj [com.rpl.specter.util-macros :only [doseqres]]))
(:require [com.rpl.specter.impl :as i]
[com.rpl.specter.navs :as n]
[clojure.set :as set])
)
[clojure.set :as set]))
(defn comp-paths
"Returns a compiled version of the given path for use with
@ -177,8 +177,8 @@
(select* [this params params-idx vals structure next-fn]
(i/exec-rich-select* nav params (- params-idx needed) vals structure next-fn))
(transform* [this params params-idx vals structure next-fn]
(i/exec-rich-transform* nav params (- params-idx needed) vals structure next-fn)
))))
(i/exec-rich-transform* nav params (- params-idx needed) vals structure next-fn)))))
;; Built-in pathing and context operations
@ -190,8 +190,8 @@
(select* [this structure next-fn]
NONE)
(transform* [this structure next-fn]
structure
))
structure))
(defnav
@ -213,8 +213,8 @@
(select* [this params params-idx vals structure next-fn]
(i/throw-illegal "'terminal' should only be used in multi-transform"))
(transform* [this params params-idx vals structure next-fn]
(n/terminal* params params-idx vals structure)
)))
(n/terminal* params params-idx vals structure))))
(defnavconstructor terminal-val
"Like `terminal` but specifies a val to set at the location regardless of
@ -240,11 +240,11 @@
[]
(select* [this structure next-fn]
(doseqres NONE [v (vals structure)]
(next-fn v)
))
(next-fn v)))
(transform* [this structure next-fn]
(n/map-vals-transform structure next-fn)
))
(n/map-vals-transform structure next-fn)))
(defcollector VAL []
@ -271,8 +271,8 @@
(select* [this structure next-fn]
(n/srange-select structure (start-fn structure) (end-fn structure) next-fn))
(transform* [this structure next-fn]
(n/srange-transform structure (start-fn structure) (end-fn structure) next-fn)
))
(n/srange-transform structure (start-fn structure) (end-fn structure) next-fn)))
(defnav
^{:doc "Navigates to the subsequence bound by the indexes start (inclusive)
@ -282,8 +282,8 @@
(select* [this structure next-fn]
(n/srange-select structure start end next-fn))
(transform* [this structure next-fn]
(n/srange-transform structure start end next-fn)
))
(n/srange-transform structure start end next-fn)))
(defnav
^{:doc "Navigates to every continuous subsequence of elements matching `pred`"}
@ -291,15 +291,15 @@
[pred]
(select* [this structure next-fn]
(doseqres NONE [[s e] (n/matching-ranges structure pred)]
(n/srange-select structure s e next-fn)
))
(n/srange-select structure s e next-fn)))
(transform* [this structure next-fn]
(reduce
(fn [structure [s e]]
(n/srange-transform structure s e next-fn))
structure
(reverse (n/matching-ranges structure pred))
)))
(reverse (n/matching-ranges structure pred)))))
(defnav
^{:doc "Navigate to the empty subsequence before the first element of the collection."}
@ -309,8 +309,8 @@
(next-fn []))
(transform* [this structure next-fn]
(let [to-prepend (next-fn [])]
(n/prepend-all structure to-prepend)
)))
(n/prepend-all structure to-prepend))))
(defnav
^{:doc "Navigate to the empty subsequence after the last element of the collection."}
@ -320,8 +320,8 @@
(next-fn []))
(transform* [this structure next-fn]
(let [to-append (next-fn [])]
(n/append-all structure to-append)
)))
(n/append-all structure to-append))))
(defnav
^{:doc "Navigates to the specified subset (by taking an intersection).
@ -336,8 +336,8 @@
newset (next-fn subset)]
(-> structure
(set/difference subset)
(set/union newset))
)))
(set/union newset)))))
(defnav
^{:doc "Navigates to the specified submap (using select-keys).
@ -401,8 +401,8 @@
(select* [this structure next-fn]
(next-fn (get structure key)))
(transform* [this structure next-fn]
(assoc structure key (next-fn (get structure key)))
))
(assoc structure key (next-fn (get structure key)))))
(defnav
^{:doc "Navigates to the key only if it exists in the map."}
@ -415,8 +415,8 @@
(transform* [this structure next-fn]
(if (contains? structure k)
(assoc structure k (next-fn (get structure k)))
structure
)))
structure)))
(defnav
^{:doc "Navigates to result of running `afn` on the currently navigated value."}
@ -425,8 +425,8 @@
(select* [this structure next-fn]
(next-fn (afn structure)))
(transform* [this structure next-fn]
(next-fn (afn structure))
))
(next-fn (afn structure))))
(defnav
^{:doc "Navigate to the result of running `parse-fn` on the value. For
@ -437,8 +437,8 @@
(select* [this structure next-fn]
(next-fn (parse-fn structure)))
(transform* [this structure next-fn]
(unparse-fn (next-fn (parse-fn structure)))
))
(unparse-fn (next-fn (parse-fn structure)))))
(defnav
^{:doc "Navigates to atom value."}
@ -522,8 +522,8 @@
(select* [this structure next-fn]
(if (afn structure) (next-fn structure) NONE))
(transform* [this structure next-fn]
(if (afn structure) (next-fn structure) structure))
)
(if (afn structure) (next-fn structure) structure)))
(extend-type nil
ImplicitNav
@ -531,8 +531,8 @@
(extend-type #?(:clj clojure.lang.Keyword :cljs cljs.core/Keyword)
ImplicitNav
(implicit-nav [this] (keypath this))
)
(implicit-nav [this] (keypath this)))
(extend-type #?(:clj clojure.lang.AFn :cljs function)
ImplicitNav
@ -586,8 +586,8 @@
[& path]
(fixed-pathed-collector [late path]
(collect-val [this structure]
(compiled-select late structure)
)))
(compiled-select late structure))))
(defpathedfn
^{:doc "Adds the result of running select-one with the given path on the
@ -596,8 +596,8 @@
[& path]
(fixed-pathed-collector [late path]
(collect-val [this structure]
(compiled-select-one late structure)
)))
(compiled-select-one late structure))))
(defcollector
^{:doc
@ -640,8 +640,8 @@
afn
then-nav
then-needed
else-nav
))
else-nav))
(transform* [this params params-idx vals structure next-fn]
(n/if-transform
params
@ -652,8 +652,8 @@
afn
then-nav
then-needed
else-nav
))))
else-nav))))
(let [cond-comp (i/comp-paths-internalized cond-p)
cond-needed (i/num-needed-params cond-comp)]
(richnav (+ then-needed else-needed cond-needed)
@ -668,8 +668,8 @@
#(n/selected?* late-cond %)
then-nav
then-needed
else-nav
)))
else-nav)))
(transform* [this params params-idx vals structure next-fn]
(let [late-cond (i/parameterize-path cond-comp params params-idx)]
(n/if-transform
@ -681,8 +681,8 @@
#(n/selected?* late-cond %)
then-nav
then-needed
else-nav
))))))))
else-nav))))))))
(defpathedfn cond-path
"Takes in alternating cond-path path cond-path path...
@ -700,8 +700,8 @@
(fn [p [tester apath]]
(if-path tester apath p))
STOP
pairs
)))
pairs)))
(defpathedfn multi-path
"A path that branches on multiple paths. For updates,
@ -713,23 +713,23 @@
comp2 (i/comp-paths-internalized path2)
comp1-needed (i/num-needed-params comp1)
nav1 (i/extract-rich-nav comp1)
nav2 (i/extract-rich-nav comp2)
]
nav2 (i/extract-rich-nav comp2)]
(richnav (+ comp1-needed (i/num-needed-params comp2))
(select* [this params params-idx vals structure next-fn]
(let [res1 (i/exec-rich-select* nav1 params params-idx vals structure next-fn)
res2 (i/exec-rich-select* nav2 params (+ params-idx comp1-needed) vals structure next-fn)]
(if (identical? NONE res2)
res1
res2
)))
res2)))
(transform* [this params params-idx vals structure next-fn]
(let [s1 (i/exec-rich-transform* nav1 params params-idx vals structure next-fn)]
(i/exec-rich-transform* nav2 params (+ params-idx comp1-needed) vals s1 next-fn)
)))))
(i/exec-rich-transform* nav2 params (+ params-idx comp1-needed) vals s1 next-fn))))))
([path1 path2 & paths]
(reduce multi-path (multi-path path1 path2) paths)
))
(reduce multi-path (multi-path path1 path2) paths)))
(defpathedfn stay-then-continue
"Navigates to the current element and then navigates via the provided path.

View file

@ -11,10 +11,9 @@
`(~invoke-name [this# ~@args]
(let [~a (~(if clj? 'com.rpl.specter.impl/fast-object-array 'object-array) ~i)]
~@setters
(com.rpl.specter.impl/bind-params* this# ~a 0)
)))]
(com.rpl.specter.impl/bind-params* this# ~a 0))))]
`(defrecord ~'ParamsNeededPath [~'rich-nav ~'num-needed-params]
~fn-type
~@impls
~var-arity-impl
)))
~var-arity-impl)))

View file

@ -3,12 +3,11 @@
(defn param-delta [i]
(fn [^objects params params-idx]
(aget params (+ params-idx i))
))
(aget params (+ params-idx i))))
(defn bound-params [path start-delta]
(fn [^objects params params-idx]
(if (i/params-needed-path? path)
(i/bind-params* path params (+ params-idx start-delta))
path
)))
path)))

View file

@ -1,19 +1,19 @@
(ns com.rpl.specter.impl
#?(:cljs (:require-macros
[com.rpl.specter.defhelpers :refer [define-ParamsNeededPath]]
[com.rpl.specter.util-macros :refer [doseqres]]
))
[com.rpl.specter.util-macros :refer [doseqres]]))
(:use [com.rpl.specter.protocols :only
[select* transform* collect-val Navigator]]
#?(:clj [com.rpl.specter.util-macros :only [doseqres]])
)
#?(:clj [com.rpl.specter.util-macros :only [doseqres]]))
(:require [com.rpl.specter.protocols :as p]
[clojure.string :as s]
#?(:clj [com.rpl.specter.defhelpers :as dh])
#?(:clj [riddley.walk :as riddley])
)
#?(:clj (:import [com.rpl.specter Util MutableCell]))
)
#?(:clj [riddley.walk :as riddley]))
#?(:clj (:import [com.rpl.specter Util MutableCell])))
(def NONE ::NONE)
@ -45,8 +45,8 @@
([a1 a2 a3 a4 a5 a6 a7 a8] v)
([a1 a2 a3 a4 a5 a6 a7 a8 a9] v)
([a1 a2 a3 a4 a5 a6 a7 a8 a9 a10] v)
([a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 & r] v)
))
([a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 & r] v)))
#?(:clj
(defmacro throw* [etype & args]
@ -60,8 +60,8 @@
:cljs
(defn throw-illegal [& args]
(throw (js/Error. (apply str args))))
)
(throw (js/Error. (apply str args)))))
;; need to get the expansion function like this so that
;; this code compiles in a clojure environment where cljs.analyzer
@ -74,8 +74,8 @@
;; this version is for bootstrap cljs
:cljs
(defn cljs-analyzer-macroexpand-1 []
^:cljs.analyzer/no-resolve cljs.analyzer/macroexpand-1)
)
^:cljs.analyzer/no-resolve cljs.analyzer/macroexpand-1))
#?(
:clj
@ -84,8 +84,8 @@
:cljs
(defn clj-macroexpand-all [form]
(throw-illegal "not implemented"))
)
(throw-illegal "not implemented")))
#?(
:clj
@ -93,8 +93,8 @@
:cljs
(defn intern* [ns name val]
(throw-illegal "intern not supported in ClojureScript"))
)
(throw-illegal "intern not supported in ClojureScript")))
(defn benchmark [iters afn]
(time
@ -107,56 +107,56 @@
(defprotocol RichNavigator
(rich-select* [this params params-idx vals structure next-fn])
(rich-transform* [this params params-idx vals structure next-fn])
)
(rich-transform* [this params params-idx vals structure next-fn]))
#?(
:clj
(defmacro exec-rich-select* [this & args]
(let [hinted (with-meta this {:tag 'com.rpl.specter.impl.RichNavigator})]
`(.rich-select* ~hinted ~@args)
))
`(.rich-select* ~hinted ~@args)))
:cljs
(defn exec-rich-select* [this params params-idx vals structure next-fn]
(rich-select* ^not-native this params params-idx vals structure next-fn))
)
(rich-select* ^not-native this params params-idx vals structure next-fn)))
#?(
:clj
(defmacro exec-rich-transform* [this & args]
(let [hinted (with-meta this {:tag 'com.rpl.specter.impl.RichNavigator})]
`(.rich-transform* ~hinted ~@args)
))
`(.rich-transform* ~hinted ~@args)))
:cljs
(defn exec-rich-transform* [this params params-idx vals structure next-fn]
(rich-transform* ^not-native this params params-idx vals structure next-fn))
)
(rich-transform* ^not-native this params params-idx vals structure next-fn)))
#?(
:clj
(defmacro exec-select* [this & args]
(let [hinted (with-meta this {:tag 'com.rpl.specter.protocols.Navigator})]
`(.select* ~hinted ~@args)
))
`(.select* ~hinted ~@args)))
:cljs
(defn exec-select* [this structure next-fn]
(p/select* ^not-native this structure next-fn))
)
(p/select* ^not-native this structure next-fn)))
#?(
:clj
(defmacro exec-transform* [this & args]
(let [hinted (with-meta this {:tag 'com.rpl.specter.protocols.Navigator})]
`(.transform* ~hinted ~@args)
))
`(.transform* ~hinted ~@args)))
:cljs
(defn exec-transform* [this structure next-fn]
(p/transform* ^not-native this structure next-fn))
)
(p/transform* ^not-native this structure next-fn)))
(def RichPathExecutor
(->ExecutorFunctions
@ -176,16 +176,16 @@
(fn [_ _ vals structure]
(if (identical? [] vals)
(transform-fn structure)
(apply transform-fn (conj vals structure))))))
))
(apply transform-fn (conj vals structure))))))))
(def LeanPathExecutor
(->ExecutorFunctions
(fn [nav result-fn structure]
(exec-select* nav structure result-fn))
(fn [nav transform-fn structure]
(exec-transform* nav structure transform-fn))
))
(exec-transform* nav structure transform-fn))))
(defrecord CompiledPath [executors nav])
@ -198,8 +198,8 @@
(->ParameterizedRichNav
rich-nav
nil
0
)))
0)))
(defn lean-compiled-path [nav]
(->CompiledPath LeanPathExecutor nav))
@ -214,8 +214,8 @@
:cljs
(defn fast-object-array [i]
(object-array i))
)
(object-array i)))
#?(
:clj
@ -240,9 +240,9 @@
[p01 p02 p03 p04 p05 p06 p07 p08 p09 p10
p11 p12 p13 p14 p15 p16 p17 p18 p19 p20]
rest))]
(com.rpl.specter.impl/bind-params* this a 0))
))
)
(com.rpl.specter.impl/bind-params* this a 0)))))
(defn params-needed-path? [o]
(instance? ParamsNeededPath o))
@ -253,8 +253,8 @@
(let [n (.-nav ^CompiledPath p)]
(if (instance? ParameterizedRichNav n)
(.-rich-nav ^ParameterizedRichNav n)
n
))))
n))))
(defn bind-params* [^ParamsNeededPath params-needed-path params idx]
@ -263,15 +263,15 @@
(->ParameterizedRichNav
(.-rich-nav params-needed-path)
params
idx
)))
idx)))
(defprotocol PathComposer
(do-comp-paths [paths]))
(defn comp-paths* [p]
(if (compiled-path? p) p (do-comp-paths p))
)
(if (compiled-path? p) p (do-comp-paths p)))
(defn- seq-contains? [aseq val]
(->> aseq
@ -285,8 +285,8 @@
(defn- coerce-object [this]
(cond (root-params-nav? this) (-> this meta :highernav :params-needed-path)
(satisfies? p/ImplicitNav this) (p/implicit-nav this)
:else (throw-illegal "Not a navigator: " this)
))
:else (throw-illegal "Not a navigator: " this)))
(defprotocol CoercePath
(coerce-path [this]))
@ -335,14 +335,14 @@
(exec-rich-select* curr params params-idx vals structure
(fn [params-next params-idx-next vals-next structure-next]
(exec-rich-select* next params-next params-idx-next
vals-next structure-next next-fn)
)))
vals-next structure-next next-fn))))
(rich-transform* [this params params-idx vals structure next-fn]
(exec-rich-transform* curr params params-idx vals structure
(fn [params-next params-idx-next vals-next structure-next]
(exec-rich-transform* next params-next params-idx-next
vals-next structure-next next-fn)
)))))
vals-next structure-next next-fn))))))
(fn [curr next]
(reify Navigator
(select* [this structure next-fn]
@ -360,11 +360,11 @@
nav
(reify RichNavigator
(rich-select* [this params params-idx vals structure next-fn]
(exec-select* nav structure (fn [structure] (next-fn params params-idx vals structure)))
)
(exec-select* nav structure (fn [structure] (next-fn params params-idx vals structure))))
(rich-transform* [this params params-idx vals structure next-fn]
(exec-transform* nav structure (fn [structure] (next-fn params params-idx vals structure)))
))))
(exec-transform* nav structure (fn [structure] (next-fn params params-idx vals structure)))))))
(defn extract-rich-nav [p]
(coerce-rich-navigator (extract-nav p)))
@ -389,13 +389,13 @@
(rich-select* [this params2 params-idx2 vals structure next-fn]
(exec-rich-select* rich-nav params params-idx vals structure
(fn [_ _ vals-next structure-next]
(next-fn params2 params-idx2 vals-next structure-next)
)))
(next-fn params2 params-idx2 vals-next structure-next))))
(rich-transform* [this params2 params-idx2 vals structure next-fn]
(exec-rich-transform* rich-nav params params-idx vals structure
(fn [_ _ vals-next structure-next]
(next-fn params2 params-idx2 vals-next structure-next)
)))))))))
(next-fn params2 params-idx2 vals-next structure-next))))))))))
(defn comp-paths-internalized [path]
(capture-params-internally (comp-paths* path)))
@ -417,14 +417,14 @@
combined (->> coerced
(map extract-nav)
(partition-by type)
(map combine-same-types)
)
(map combine-same-types))
result-nav (if (= 1 (count combined))
(first combined)
(->> combined
(map coerce-rich-navigator)
combine-same-types)
)
combine-same-types))
needs-params-paths (filter #(instance? ParamsNeededPath %) coerced)]
(if (empty? needs-params-paths)
(if (satisfies? Navigator result-nav)
@ -434,9 +434,9 @@
(coerce-rich-navigator result-nav)
(->> needs-params-paths
(map :num-needed-params)
(reduce +))
))
))))
(reduce +))))))))
(defn num-needed-params [path]
@ -448,14 +448,14 @@
;; cell implementation idea taken from prismatic schema library
#?(:cljs
(defprotocol PMutableCell
(set_cell [cell x]))
)
(set_cell [cell x])))
#?(:cljs
(deftype MutableCell [^:volatile-mutable q]
PMutableCell
(set_cell [this x] (set! q x)))
)
(set_cell [this x] (set! q x))))
#?(
:clj
@ -466,8 +466,8 @@
:cljs
(defn mutable-cell
([] (mutable-cell nil))
([init] (MutableCell. init)))
)
([init] (MutableCell. init))))
#?(
:clj
@ -476,8 +476,8 @@
:cljs
(defn set-cell! [cell val]
(set_cell cell val))
)
(set_cell cell val)))
#?(
:clj
@ -487,8 +487,8 @@
:cljs
(defn get-cell [cell]
(.-q cell))
)
(.-q cell)))
@ -520,8 +520,8 @@
((traverse-executor-field ex#)
nav#
~result-fn
~structure)
))
~structure)))
:cljs
(defn compiled-traverse* [path result-fn structure]
@ -530,9 +530,9 @@
((traverse-executor-field ex)
nav
result-fn
structure)
))
)
structure))))
(defn do-compiled-traverse [apath structure]
(reify #?(:clj clojure.lang.IReduce :cljs cljs.core/IReduce)
@ -546,22 +546,22 @@
apath
(fn [elem]
(let [curr (get-cell cell)]
(set-cell! cell (afn curr elem))
))
structure
)
(get-cell cell)
))))
(set-cell! cell (afn curr elem))))
structure)
(get-cell cell)))))
(defn compiled-select* [path structure]
(let [res (mutable-cell (transient []))
result-fn (fn [structure]
(let [curr (get-cell res)]
(set-cell! res (conj! curr structure))
))]
(set-cell! res (conj! curr structure))))]
(compiled-traverse* path result-fn structure)
(persistent! (get-cell res))
))
(persistent! (get-cell res))))
(defn compiled-select-one* [path structure]
(let [res (mutable-cell NONE)
@ -569,14 +569,14 @@
(let [curr (get-cell res)]
(if (identical? curr NONE)
(set-cell! res structure)
(throw-illegal "More than one element found in structure: " structure)
)))]
(throw-illegal "More than one element found in structure: " structure))))]
(compiled-traverse* path result-fn structure)
(let [ret (get-cell res)]
(if (identical? ret NONE)
nil
ret
))))
ret))))
(defn compiled-select-one!* [path structure]
(let [res (mutable-cell NONE)
@ -584,14 +584,14 @@
(let [curr (get-cell res)]
(if (identical? curr NONE)
(set-cell! res structure)
(throw-illegal "More than one element found in structure: " structure)
)))]
(throw-illegal "More than one element found in structure: " structure))))]
(compiled-traverse* path result-fn structure)
(let [ret (get-cell res)]
(if (identical? NONE ret)
(throw-illegal "Found no elements for select-one! on " structure))
ret
)))
ret)))
(defn compiled-select-first* [path structure]
(let [res (mutable-cell NONE)
@ -603,8 +603,8 @@
(let [ret (get-cell res)]
(if (identical? ret NONE)
nil
ret
))))
ret))))
(defn compiled-select-any* [path structure]
(compiled-traverse* path identity structure))
@ -616,8 +616,8 @@
[^com.rpl.specter.impl.CompiledPath path transform-fn structure]
(let [nav (.-nav path)
^com.rpl.specter.impl.ExecutorFunctions ex (.-executors path)]
((.-transform-executor ex) nav transform-fn structure)
))
((.-transform-executor ex) nav transform-fn structure)))
(defn params-needed-nav
@ -629,8 +629,8 @@
^com.rpl.specter.impl.RichNavigator
[^com.rpl.specter.impl.CompiledPath path]
(let [^com.rpl.specter.impl.ParameterizedRichNav pr (.-nav path)]
(.-rich-nav pr)
))
(.-rich-nav pr)))
(defn coerce-compiled->rich-nav [path]
(if (instance? ParamsNeededPath path)
@ -638,8 +638,8 @@
(let [nav (.-nav ^CompiledPath path)]
(if (satisfies? Navigator nav)
(no-params-rich-compiled-path (coerce-rich-navigator nav))
path
))))
path))))
(defn fn-invocation? [f]
(or #?(:clj (instance? clojure.lang.Cons f))
@ -660,8 +660,8 @@
(and (instance? ParamsNeededPath anav)
(> (:num-needed-params anav) 0)))
(throw-illegal "defnavconstructor must be used on a navigator defined with
defnav with at least one parameter")
))
defnav with at least one parameter")))
(defn layered-wrapper [anav]
(verify-layerable! anav)
@ -676,8 +676,8 @@
([a1 a2 a3 a4 a5 a6 a7 a8 a9] (->LayeredNav (anav a1 a2 a3 a4 a5 a6 a7 a8 a9)))
([a1 a2 a3 a4 a5 a6 a7 a8 a9 a10] (->LayeredNav (anav a1 a2 a3 a4 a5 a6 a7 a8 a9 a10)))
([a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 & args]
(->LayeredNav (apply anav a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 args)))
))
(->LayeredNav (apply anav a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 args)))))
(defrecord LocalSym
[val sym])
@ -694,8 +694,8 @@
(defrecord CachedPathInfo
[precompiled ; can be null
params-maker ; can be null
])
params-maker]) ; can be null
(def MUST-CACHE-PATHS (mutable-cell false))
@ -712,8 +712,8 @@
(set? node) (every? constant-node? node)
(map? node) (and (every? constant-node? (vals node))
(every? constant-node? (keys node)))
:else false
))
:else false))
(defn- extract-original-code [p]
(cond
@ -721,8 +721,8 @@
(instance? VarUse p) (:sym p)
(instance? SpecialFormUse p) (:code p)
(instance? FnInvocation p) (:code p)
:else p
))
:else p))
(defn- valid-navigator? [v]
(or (satisfies? p/ImplicitNav v)
@ -733,8 +733,8 @@
(let [params (fast-object-array (count params-maker))]
(dotimes [i (count params-maker)]
(aset params i ((get possible-params (get params-maker i)))))
(bind-params* precompiled params 0)
)))
(bind-params* precompiled params 0))))
(defn filter-select [afn structure next-fn]
(if (afn structure)
@ -753,16 +753,16 @@
(let [afn (aget ^objects params params-idx)]
(if (afn structure)
(next-fn params (inc params-idx) vals structure)
NONE
)))
NONE)))
(rich-transform* [this params params-idx vals structure next-fn]
(let [afn (aget ^objects params params-idx)]
(if (afn structure)
(next-fn params (inc params-idx) vals structure)
structure
))))
1
))
structure))))
1))
(def collected?*
(->ParamsNeededPath
@ -771,16 +771,16 @@
(let [afn (aget ^objects params params-idx)]
(if (afn vals)
(next-fn params (inc params-idx) vals structure)
NONE
)))
NONE)))
(rich-transform* [this params params-idx vals structure next-fn]
(let [afn (aget ^objects params params-idx)]
(if (afn vals)
(next-fn params (inc params-idx) vals structure)
structure
))))
1
))
structure))))
1))
(def rich-compiled-path-proxy
(->ParamsNeededPath
@ -796,8 +796,8 @@
vals
structure
(fn [_ _ vals-next structure-next]
(next-fn params params-idx vals-next structure-next))
)))
(next-fn params params-idx vals-next structure-next)))))
(rich-transform* [this params params-idx vals structure next-fn]
(let [apath ^CompiledPath (aget ^objects params params-idx)
pnav ^ParameterizedRichNav (.-nav apath)
@ -809,10 +809,10 @@
vals
structure
(fn [_ _ vals-next structure-next]
(next-fn params params-idx vals-next structure-next))
))))
1
))
(next-fn params params-idx vals-next structure-next))))))
1))
(def lean-compiled-path-proxy
(->ParamsNeededPath
@ -824,8 +824,8 @@
nav
structure
(fn [structure-next]
(next-fn params params-idx vals structure-next))
)))
(next-fn params params-idx vals structure-next)))))
(rich-transform* [this params params-idx vals structure next-fn]
(let [^CompiledPath apath (aget ^objects params params-idx)
^Navigator nav (.-nav apath)]
@ -833,10 +833,10 @@
nav
structure
(fn [structure-next]
(next-fn params params-idx vals structure-next))
))))
1
))
(next-fn params params-idx vals structure-next))))))
1))
(defn srange-transform* [structure start end next-fn]
(let [structurev (vec structure)
@ -846,8 +846,8 @@
(subvec structurev end (count structure)))]
(if (vector? structure)
(vec res)
res
)))
res)))
(defn- variadic-arglist? [al]
(contains? (set al) '&))
@ -857,8 +857,8 @@
(filter
(fn [al]
(or (= (count al) c)
(variadic-arglist? al))
))
(variadic-arglist? al))))
first)
len (count ret)]
(when-not ret
@ -866,8 +866,8 @@
(if (variadic-arglist? ret)
(srange-transform* ret (- len 2) len
(fn [_] (repeatedly (- c (- len 2)) gensym)))
ret
)))
ret)))
(defn- magic-precompilation* [p params-atom failed-atom]
(let [magic-fail! (fn [& reason]
@ -897,17 +897,17 @@
vv
:else
(magic-fail! "Var " (:sym p) " is not a navigator")
))
(magic-fail! "Var " (:sym p) " is not a navigator")))
(instance? SpecialFormUse p)
(if (->> p :code first (contains? #{'fn* 'fn}))
(do
(swap! params-atom conj (:code p))
pred*
)
(magic-fail! "Special form " (:code p) " where navigator expected")
)
pred*)
(magic-fail! "Special form " (:code p) " where navigator expected"))
(instance? FnInvocation p)
(let [op (:op p)
@ -923,8 +923,8 @@
(apply vv ps)
(do
(swap! params-atom #(vec (concat % ps)))
(coerce-path vv)
))
(coerce-path vv)))
(and (fn? vv) (-> v meta :pathedfn))
;;TODO: update this to ignore args that aren't symbols or have :nopath
@ -953,14 +953,14 @@
(magic-fail! "Could not factor static param "
"of pathedfn because it's not a static var "
" or non-collection value: "
(extract-original-code p))
)))
(extract-original-code p)))))
al
ps))]
(if @failed-atom
nil
(apply vv subpath)
))
(apply vv subpath)))
(and (fn? vv) (-> vv meta :layerednav))
(if (every? constant-node? ps)
@ -969,20 +969,20 @@
(swap! params-atom conj (:code p))
(if (= (-> vv meta :layerednav) :lean)
lean-compiled-path-proxy
rich-compiled-path-proxy
)))
rich-compiled-path-proxy)))
:else
(magic-fail! "Var " (:sym op) " must be either a parameterized "
"navigator, a higher order pathed constructor function, "
"or a nav constructor")
)))
"or a nav constructor"))))
(magic-fail! "Code at " (extract-original-code p) " is in "
"function invocation position and must be either a parameterized "
"navigator, a higher order pathed constructor function, or a "
"nav constructor."
)
))
"nav constructor.")))
:else
(cond (set? p)
@ -999,9 +999,9 @@
p
:else
(magic-fail! "Code " p " is not a valid navigator or can't be factored")
)
)))
(magic-fail! "Code " p " is not a valid navigator or can't be factored")))))
;; This is needed when aset is used on primitive values in mk-params-maker
@ -1022,10 +1022,10 @@
~@(map-indexed
(fn [i c]
`(aset-object ~array-sym ~i ~c))
params-code
)
~array-sym
))))))
params-code)
~array-sym))))))
:cljs
(defn mk-params-maker [ns-str params-code possible-params-code used-locals]
@ -1033,15 +1033,15 @@
(map-indexed (comp vec reverse vector))
(into {}))]
;;TODO: may be more efficient as an array
(mapv (fn [c] (get indexed c)) params-code)))
)
(mapv (fn [c] (get indexed c)) params-code))))
;; possible-params-code is for cljs impl that can't use eval
(defn magic-precompilation [prepared-path ns-str used-locals possible-params-code]
(let [params-atom (atom [])
failed-atom (atom false)
path (magic-precompilation* prepared-path params-atom failed-atom)
]
path (magic-precompilation* prepared-path params-atom failed-atom)]
(if @failed-atom
(if (get-cell MUST-CACHE-PATHS)
(throw-illegal "Failed to cache path")
@ -1049,13 +1049,13 @@
(let [precompiled (comp-paths* path)
params-code (mapv extract-original-code @params-atom)
params-maker (if-not (empty? params-code)
(mk-params-maker ns-str params-code possible-params-code used-locals))
]
(mk-params-maker ns-str params-code possible-params-code used-locals))]
;; TODO: error if precompiled is compiledpath and there are params or
;; precompiled is paramsneededpath and there are no params...
(->CachedPathInfo precompiled params-maker)
))
))
(->CachedPathInfo precompiled params-maker)))))
@ -1074,11 +1074,11 @@
(merge-fn (get-cell state))
(set-cell! state))
ret)
(last args)
)))
(last args))))
structure)
(get-cell state)]
))
(get-cell state)]))
(defn- multi-transform-error-fn [& nav]
(throw-illegal
@ -1096,22 +1096,21 @@
(doseq [[atype apath] extensions]
(let [p (comp-paths-internalized apath)
needed-params (num-needed-params p)
rich-nav (extract-rich-nav p)
]
rich-nav (extract-rich-nav p)]
(if-not (= needed-params expected-params)
(throw-illegal "Invalid number of params in extended protocol path, expected "
expected-params " but got " needed-params))
(extend atype protpath-prot {m (fn [_] rich-nav)})
)))))
(extend atype protpath-prot {m (fn [_] rich-nav)}))))))
(defn parameterize-path [apath params params-idx]
(if (instance? CompiledPath apath)
apath
(bind-params* apath params params-idx)
))
(bind-params* apath params params-idx)))
(defn mk-jump-next-fn [next-fn init-idx total-params]
(let [jumped (+ init-idx total-params)]
(fn [params params-idx vals structure]
(next-fn params jumped vals structure)
)))
(next-fn params jumped vals structure))))

View file

@ -3,8 +3,8 @@
[com.rpl.specter.impl :only [RichNavigator]])
(:require [com.rpl.specter.impl :as i]
[clojure.walk :as cljwalk]
[com.rpl.specter.defnavhelpers :as dnh])
)
[com.rpl.specter.defnavhelpers :as dnh]))
(defn ^:no-doc gensyms [amt]
(vec (repeatedly amt gensym)))
@ -14,8 +14,8 @@
(if-not (= #{'select* 'transform*} (-> grouped keys set))
(i/throw-illegal "defnav must implement select* and transform*, instead got "
(keys grouped)))
grouped
))
grouped))
(defmacro richnav
"Defines a navigator with full access to collected vals, the parameters array,
@ -30,8 +30,8 @@
s-next-fn-sym (last s-params)
s-pidx-sym (nth s-params 2)
t-next-fn-sym (last t-params)
t-pidx-sym (nth t-params 2)
]
t-pidx-sym (nth t-params 2)]
`(let [num-params# ~num-params
nav# (reify RichNavigator
(~'rich-select* ~s-params
@ -39,12 +39,12 @@
~@s-body))
(~'rich-transform* ~t-params
(let [~t-next-fn-sym (i/mk-jump-next-fn ~t-next-fn-sym ~t-pidx-sym num-params#)]
~@t-body))
)]
~@t-body)))]
(if (zero? num-params#)
(i/no-params-rich-compiled-path nav#)
(i/->ParamsNeededPath nav# num-params#)
))))
(i/->ParamsNeededPath nav# num-params#)))))
(defmacro ^:no-doc lean-nav* [& impls]
`(reify Navigator ~@impls))
@ -60,16 +60,15 @@
binding-fn-syms))
body (op-maker binding-declarations)]
`(let [~@binding-fn-declarations]
~body
)))
~body)))
(defmacro ^:no-doc rich-nav-with-bindings [num-params-code bindings & impls]
(let [{[[_ s-structure-sym s-next-fn-sym] & s-body] 'select*
[[_ t-structure-sym t-next-fn-sym] & t-body] 'transform*}
(determine-params-impls impls)
params-sym (gensym "params")
params-idx-sym (gensym "params-idx")
]
params-idx-sym (gensym "params-idx")]
(operation-with-bindings
bindings
params-sym
@ -84,8 +83,8 @@
next-params-idx#
vals#
structure#))]
~@s-body
))
~@s-body))
(~'rich-transform* [this# ~params-sym ~params-idx-sym vals# ~t-structure-sym next-fn#]
(let [~@binding-declarations
next-params-idx# (+ ~params-idx-sym ~num-params-code)
@ -94,9 +93,9 @@
next-params-idx#
vals#
structure#))]
~@t-body
))
)))))
~@t-body)))))))
(defmacro ^:no-doc collector-with-bindings [num-params-code bindings impl]
(let [[_ [_ structure-sym] & body] impl
@ -110,21 +109,21 @@
`(let [num-params# ~num-params-code
cfn# (fn [~params-sym ~params-idx-sym vals# ~structure-sym next-fn#]
(let [~@binding-declarations]
(next-fn# ~params-sym (+ ~params-idx-sym num-params#) (conj vals# (do ~@body)) ~structure-sym)
))]
(next-fn# ~params-sym (+ ~params-idx-sym num-params#) (conj vals# (do ~@body)) ~structure-sym)))]
(reify RichNavigator
(~'rich-select* [this# params# params-idx# vals# structure# next-fn#]
(cfn# params# params-idx# vals# structure# next-fn#))
(~'rich-transform* [this# params# params-idx# vals# structure# next-fn#]
(cfn# params# params-idx# vals# structure# next-fn#))
))))))
(cfn# params# params-idx# vals# structure# next-fn#))))))))
(defn- delta-param-bindings [params]
(->> params
(map-indexed (fn [i p] [p `(dnh/param-delta ~i)]))
(apply concat)
vec
))
vec))
(defmacro nav
"Defines a navigator with late bound parameters. This navigator can be precompiled
@ -143,10 +142,10 @@
(i/->ParamsNeededPath
(rich-nav-with-bindings ~(count params)
~(delta-param-bindings params)
~@impls
)
~(count params))}
)))
~@impls)
~(count params))})))
(defmacro collector
"Defines a Collector with late bound parameters. This collector can be precompiled
@ -157,8 +156,8 @@
[params body]
`(let [rich-nav# (collector-with-bindings ~(count params)
~(delta-param-bindings params)
~body
)]
~body)]
(if ~(empty? params)
(i/no-params-rich-compiled-path rich-nav#)
(vary-meta
@ -172,9 +171,9 @@
:params-needed-path
(i/->ParamsNeededPath
rich-nav#
~(count params)
)}
))))
~(count params))}))))
(defn ^:no-doc fixed-pathed-operation [bindings op-maker]
(let [bindings (partition 2 bindings)
@ -184,8 +183,8 @@
compiled-syms (vec (gensyms (count bindings)))
runtime-bindings (vec (mapcat
(fn [l c d]
`[~l (dnh/bound-params ~c ~d)]
)
`[~l (dnh/bound-params ~c ~d)])
late-path-syms
compiled-syms
delta-syms))
@ -195,10 +194,10 @@
~compiled-syms compiled#
deltas# (cons 0 (reductions + (map i/num-needed-params compiled#)))
~delta-syms deltas#
~total-params-sym (last deltas#)
]
~body
)))
~total-params-sym (last deltas#)]
~body)))
(defmacro fixed-pathed-nav
"This helper is used to define navigators that take in a fixed number of other
@ -212,16 +211,16 @@
lean-bindings (mapcat vector late-syms compiled-syms)]
`(if (zero? ~total-params-sym)
(let [~@lean-bindings]
(i/lean-compiled-path (lean-nav* ~@impls))
)
(i/lean-compiled-path (lean-nav* ~@impls)))
(i/->ParamsNeededPath
(rich-nav-with-bindings ~total-params-sym
~runtime-bindings
~@impls
)
~total-params-sym
)))
)))
~@impls)
~total-params-sym))))))
(defmacro fixed-pathed-collector
@ -241,21 +240,21 @@
(i/->ParamsNeededPath
(collector-with-bindings ~total-params-sym
~runtime-bindings
~@body
)
~total-params-sym
))))))
~@body)
~total-params-sym))))))
(defmacro paramsfn [params [structure-sym] & impl]
`(nav ~params
(~'select* [this# structure# next-fn#]
(let [afn# (fn [~structure-sym] ~@impl)]
(i/filter-select afn# structure# next-fn#)
))
(i/filter-select afn# structure# next-fn#)))
(~'transform* [this# structure# next-fn#]
(let [afn# (fn [~structure-sym] ~@impl)]
(i/filter-transform afn# structure# next-fn#)
))))
(i/filter-transform afn# structure# next-fn#)))))
(defmacro defnav [name & body]
`(def ~name (nav ~@body)))
@ -293,24 +292,24 @@
num-params (count params)
ssym (gensym "structure")
rargs [(gensym "params") (gensym "pidx") (gensym "vals") ssym (gensym "next-fn")]
retrieve `(~m ~ssym)
]
retrieve `(~m ~ssym)]
`(do
(defprotocol ~prot-name (~m [structure#]))
(let [nav# (reify RichNavigator
(~'rich-select* [this# ~@rargs]
(let [inav# ~retrieve]
(i/exec-rich-select* inav# ~@rargs)
))
(i/exec-rich-select* inav# ~@rargs)))
(~'rich-transform* [this# ~@rargs]
(let [inav# ~retrieve]
(i/exec-rich-transform* inav# ~@rargs)
)))]
(i/exec-rich-transform* inav# ~@rargs))))]
(def ~name
(if (= ~num-params 0)
(i/no-params-rich-compiled-path nav#)
(i/->ParamsNeededPath nav# ~num-params)
)))))))
(i/->ParamsNeededPath nav# ~num-params))))))))
@ -342,12 +341,12 @@
(~'rich-select* [this# ~@rargs]
(~select-exec ~declared ~@rargs))
(~'rich-transform* [this# ~@rargs]
(~transform-exec ~declared ~@rargs)
))]
(~transform-exec ~declared ~@rargs)))]
(if (= ~num-params 0)
(i/no-params-rich-compiled-path nav#)
(i/->ParamsNeededPath nav# ~num-params)
)))))))
(i/->ParamsNeededPath nav# ~num-params))))))))
(defmacro providepath [name apath]
`(let [comped# (i/comp-paths-internalized ~apath)
@ -357,8 +356,8 @@
(i/throw-illegal "Invalid number of params in provided path, expected "
expected-params# " but got " needed-params#))
(def ~(declared-name name)
(i/extract-rich-nav (i/coerce-compiled->rich-nav comped#))
)))
(i/extract-rich-nav (i/coerce-compiled->rich-nav comped#)))))
(defmacro extend-protocolpath
"Used in conjunction with `defprotocolpath`. See [[defprotocolpath]]."
@ -420,15 +419,15 @@
(i/throw-illegal "Expected result navigator '" (quote ~anav)
"' from nav constructor '" (quote ~name) "'"
" constructed with the provided constructor '" (quote ~csym)
"'"))
))))]
"'"))))))]
`(def ~name
(vary-meta
(let [~csym (i/layered-wrapper ~anav)]
(fn ~@checked-code))
assoc :layerednav (or (-> ~anav meta :highernav :type) :rich)
))
))
assoc :layerednav (or (-> ~anav meta :highernav :type) :rich)))))
(defn ^:no-doc ic-prepare-path [locals-set path]
@ -440,8 +439,8 @@
(if (contains? locals-set path)
`(com.rpl.specter.impl/->LocalSym ~path (quote ~path))
;; var-get doesn't work in cljs, so capture the val in the macro instead
`(com.rpl.specter.impl/->VarUse ~path (var ~path) (quote ~path))
)
`(com.rpl.specter.impl/->VarUse ~path (var ~path) (quote ~path)))
(i/fn-invocation? path)
(let [[op & params] path]
@ -452,12 +451,12 @@
`(com.rpl.specter.impl/->FnInvocation
~(ic-prepare-path locals-set op)
~(mapv #(ic-prepare-path locals-set %) params)
(quote ~path)))
)
(quote ~path))))
:else
`(quote ~path)
))
`(quote ~path)))
(defn ^:no-doc ic-possible-params [path]
(do
@ -473,10 +472,10 @@
(concat [e] (rest e) (ic-possible-params e))
(vector? e)
(ic-possible-params e)
))
path
)))
(ic-possible-params e)))
path)))
(defn cljs-macroexpand [env form]
(let [expand-fn (i/cljs-analyzer-macroexpand-1)
@ -490,13 +489,13 @@
(#{'fn 'fn* 'cljs.core/fn} (first form)))
form
(let [expanded (if (seq? form) (cljs-macroexpand env form) form)]
(cljwalk/walk #(cljs-macroexpand-all* env %) identity expanded)
)))
(cljwalk/walk #(cljs-macroexpand-all* env %) identity expanded))))
(defn cljs-macroexpand-all [env form]
(let [ret (cljs-macroexpand-all* env form)]
ret
))
ret))
;; still possible to mess this up with alter-var-root
(defmacro path
@ -509,15 +508,15 @@
platform (if (contains? &env :locals) :cljs :clj)
local-syms (if (= platform :cljs)
(-> &env :locals keys set) ;cljs
(-> &env keys set) ;clj
)
(-> &env keys set)) ;clj
used-locals-cell (i/mutable-cell [])
_ (cljwalk/postwalk
(fn [e]
(if (local-syms e)
(i/update-cell! used-locals-cell #(conj % e))
e
))
e))
path)
used-locals (i/get-cell used-locals-cell)
@ -549,10 +548,10 @@
(alter-var-root
(var ~cache-sym)
(fn [_#] (i/mutable-cell)))
nil
))))
cache-sym
)
nil))))
cache-sym)
add-cache-code (if (= platform :clj)
`(i/set-cell! ~cache-sym ~info-sym)
`(def ~cache-sym ~info-sym))
@ -567,9 +566,9 @@
`(i/handle-params
~precompiled-sym
~params-maker-sym
~(mapv (fn [p] `(fn [] ~p)) possible-params)
))
]
~(mapv (fn [p] `(fn [] ~p)) possible-params)))]
(if (= platform :clj)
(i/intern* *ns* cache-sym (i/mutable-cell)))
`(let [info# ~get-cache-code
@ -580,13 +579,13 @@
~prepared-path
~(str *ns*)
(quote ~used-locals)
(quote ~possible-params)
)]
(quote ~possible-params))]
~add-cache-code
~info-sym
)
info#
)
~info-sym)
info#)
~precompiled-sym (.-precompiled info#)
~params-maker-sym (.-params-maker info#)]
@ -594,10 +593,10 @@
(i/comp-paths* ~(if (= (count path) 1) (first path) (vec path)))
(if (nil? ~params-maker-sym)
~precompiled-sym
~handle-params-code
)
))
))
~handle-params-code)))))
(defmacro select
"Navigates to and returns a sequence of all the elements specified by the path.
@ -705,5 +704,4 @@
to capture all the collected values as a single vector."
[params & body]
(let [platform (if (contains? &env :locals) :cljs :clj)]
`(i/collected?* (~'fn [~params] ~@body))
))
`(i/collected?* (~'fn [~params] ~@body))))

View file

@ -8,19 +8,19 @@
defnav
defpathedfn
richnav
defnavconstructor
]]
defnavconstructor]]
[com.rpl.specter.util-macros :refer
[doseqres]]
))
[doseqres]]))
(:use #?(:clj [com.rpl.specter macros])
#?(: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])
[com.rpl.specter.defnavhelpers] ; so that for cljs it's loaded as macros expand to this
)
)
[com.rpl.specter.defnavhelpers])) ; so that for cljs it's loaded as macros expand to this
(defn- append [coll elem]
(-> coll vec (conj elem)))
@ -42,20 +42,20 @@
(let [r (continue-fn structure)]
(if-not (identical? r i/NONE)
(i/set-cell! ret r))
r
)
(walk/walk this identity structure)
))]
r)
(walk/walk this identity structure)))]
(walker structure)
(i/get-cell ret)
))
(i/get-cell ret)))
(defn key-select [akey structure next-fn]
(next-fn (get structure akey)))
(defn key-transform [akey structure next-fn]
(assoc structure akey (next-fn (get structure akey))
))
(assoc structure akey (next-fn (get structure akey))))
(defn all-select [structure next-fn]
(doseqres i/NONE [e structure]
@ -68,8 +68,8 @@
:cljs
(defn queue? [coll]
(= (type coll) (type #queue [])))
)
(= (type coll) (type #queue []))))
(defprotocol AllTransformProtocol
(all-transform [structure next-fn]))
@ -78,17 +78,17 @@
(reduce-kv
(fn [m k v]
(let [[newk newv] (next-fn [k v])]
(assoc m newk newv)
))
(assoc m newk newv)))
empty-map
structure
))
structure))
(extend-protocol AllTransformProtocol
nil
(all-transform [structure next-fn]
nil
)
nil)
;; in cljs they're PersistentVector so don't need a special case
#?(:clj clojure.lang.MapEntry)
@ -96,8 +96,8 @@
(all-transform [structure next-fn]
(let [newk (next-fn (key structure))
newv (next-fn (val structure))]
(clojure.lang.MapEntry. newk newv)
)))
(clojure.lang.MapEntry. newk newv))))
#?(:clj clojure.lang.PersistentVector :cljs cljs.core/PersistentVector)
(all-transform [structure next-fn]
@ -117,19 +117,19 @@
(aset array i newk)
(aset array (inc i) newv)
(recur (+ i 2)))))
(clojure.lang.PersistentArrayMap. array)
)))
(clojure.lang.PersistentArrayMap. array))))
#?(:cljs cljs.core/PersistentArrayMap)
#?(:cljs
(all-transform [structure next-fn]
(non-transient-map-all-transform structure next-fn {})
))
(non-transient-map-all-transform structure next-fn {})))
#?(:clj clojure.lang.PersistentTreeMap :cljs cljs.core/PersistentTreeMap)
(all-transform [structure next-fn]
(non-transient-map-all-transform structure next-fn (empty structure))
)
(non-transient-map-all-transform structure next-fn (empty structure)))
#?(:clj clojure.lang.PersistentHashMap :cljs cljs.core/PersistentHashMap)
(all-transform [structure next-fn]
@ -137,13 +137,13 @@
(reduce-kv
(fn [m k v]
(let [[newk newv] (next-fn [k v])]
(assoc! m newk newv)
))
(assoc! m newk newv)))
(transient
#?(:clj clojure.lang.PersistentHashMap/EMPTY :cljs cljs.core.PersistentHashMap.EMPTY)
)
structure
)))
#?(:clj clojure.lang.PersistentHashMap/EMPTY :cljs cljs.core.PersistentHashMap.EMPTY))
structure)))
#?(:clj Object)
@ -159,15 +159,15 @@
(reduce-kv
(fn [m k v]
(let [[newk newv] (next-fn [k v])]
(assoc m newk newv)
))
(assoc m newk newv)))
empty-structure
structure
)
structure)
:else
(->> structure (r/map next-fn) (into empty-structure))
))))
(->> structure (r/map next-fn) (into empty-structure))))))
#?(:cljs default)
#?(:cljs
@ -176,9 +176,9 @@
(if (and (list? empty-structure) (not (queue? empty-structure)))
;; this is done to maintain order, otherwise lists get reversed
(doall (map next-fn structure))
(into empty-structure (map #(next-fn %)) structure)
))))
)
(into empty-structure (map #(next-fn %)) structure))))))
(defprotocol MapValsTransformProtocol
(map-vals-transform [structure next-fn]))
@ -193,8 +193,8 @@
(extend-protocol MapValsTransformProtocol
nil
(map-vals-transform [structure next-fn]
nil
)
nil)
#?(:clj clojure.lang.PersistentArrayMap)
#?(:clj
@ -210,19 +210,19 @@
(aset array i k)
(aset array (inc i) newv)
(recur (+ i 2)))))
(clojure.lang.PersistentArrayMap. array)
)))
(clojure.lang.PersistentArrayMap. array))))
#?(:cljs cljs.core/PersistentArrayMap)
#?(:cljs
(map-vals-transform [structure next-fn]
(map-vals-non-transient-transform structure {} next-fn)
))
(map-vals-non-transient-transform structure {} next-fn)))
#?(:clj clojure.lang.PersistentTreeMap :cljs cljs.core/PersistentTreeMap)
(map-vals-transform [structure next-fn]
(map-vals-non-transient-transform structure (empty structure) next-fn)
)
(map-vals-non-transient-transform structure (empty structure) next-fn))
#?(:clj clojure.lang.PersistentHashMap :cljs cljs.core/PersistentHashMap)
(map-vals-transform [structure next-fn]
@ -231,10 +231,10 @@
(fn [m k v]
(assoc! m k (next-fn v)))
(transient
#?(:clj clojure.lang.PersistentHashMap/EMPTY :cljs cljs.core.PersistentHashMap.EMPTY)
)
structure
)))
#?(:clj clojure.lang.PersistentHashMap/EMPTY :cljs cljs.core.PersistentHashMap.EMPTY))
structure)))
#?(:clj Object :cljs default)
(map-vals-transform [structure next-fn]
@ -242,8 +242,8 @@
(fn [m k v]
(assoc m k (next-fn v)))
(empty structure)
structure))
)
structure)))
(defn srange-select [structure start end next-fn]
(next-fn (-> structure vec (subvec start end))))
@ -265,11 +265,11 @@
[ranges curr-start i]
:else
[(conj ranges [curr-start (inc curr-last)]) i i]
))
[(conj ranges [curr-start (inc curr-last)]) i i]))
[[] nil nil]
(concat (matching-indices aseq p) [-1])
)))
(concat (matching-indices aseq p) [-1]))))
(defn extract-basic-filter-fn [path]
(cond (fn? path)
@ -280,10 +280,10 @@
(reduce
(fn [combined afn]
(fn [structure]
(and (combined structure) (afn structure))
))
path
)))
(and (combined structure) (afn structure))))
path)))
@ -299,8 +299,8 @@
idx
vals
structure
next-fn
)))
next-fn)))
(defn if-transform [params params-idx vals structure next-fn then-tester then-nav then-params else-nav]
@ -315,15 +315,15 @@
idx
vals
structure
next-fn
)))
next-fn)))
(defn terminal* [params params-idx vals structure]
(let [afn (aget ^objects params params-idx)]
(if (identical? vals [])
(afn structure)
(apply afn (conj vals structure)))
))
(apply afn (conj vals structure)))))
(defprotocol AddExtremes
@ -345,15 +345,15 @@
(as-> ret <>
(reduce conj! <> elements)
(reduce conj! <> structure)
(persistent! <>)
)))
(persistent! <>))))
#?(:clj Object :cljs default)
(append-all [structure elements]
(concat structure elements))
(prepend-all [structure elements]
(concat elements structure))
)
(concat elements structure)))
(defprotocol UpdateExtremes
@ -390,8 +390,8 @@
:cljs
(defn vec-count [v]
(count v))
)
(count v)))
#?(
:clj
@ -400,15 +400,15 @@
:cljs
(defn transient-vec-count [v]
(count v))
)
(count v)))
(extend-protocol UpdateExtremes
#?(:clj clojure.lang.PersistentVector :cljs cljs.core/PersistentVector)
(update-first [v afn]
(let [val (nth v 0)]
(assoc v 0 (afn val))
))
(assoc v 0 (afn val))))
(update-last [v afn]
;; type-hinting vec-count to ^int caused weird errors with case
(let [c (int (vec-count v))]
@ -416,14 +416,14 @@
1 (let [[e] v] [(afn e)])
2 (let [[e1 e2] v] [e1 (afn e2)])
(let [i (dec c)]
(assoc v i (afn (nth v i)))
))))
(assoc v i (afn (nth v i)))))))
#?(:clj Object :cljs default)
(update-first [l val]
(update-first-list l val))
(update-last [l val]
(update-last-list l val)
))
(update-last-list l val)))
(extend-protocol GetExtremes
#?(:clj clojure.lang.IPersistentVector :cljs cljs.core/PersistentVector)
@ -435,8 +435,8 @@
(get-first [s]
(first s))
(get-last [s]
(last s)
))
(last s)))
(extend-protocol FastEmpty
@ -451,14 +451,14 @@
(= 0 (transient-vec-count v)))
#?(:clj Object :cljs default)
(fast-empty? [s]
(empty? s))
)
(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)
))
(walk/walk (partial walk-until pred on-match-fn) identity structure)))
(defn codewalk-until [pred on-match-fn structure]
(if (pred structure)
@ -466,8 +466,8 @@
(let [ret (walk/walk (partial codewalk-until pred on-match-fn) identity structure)]
(if (and (i/fn-invocation? structure) (i/fn-invocation? ret))
(with-meta ret (meta structure))
ret
))))
ret))))
(def DISPENSE*
(i/no-params-rich-compiled-path

View file

@ -15,8 +15,8 @@
(transform* [this structure next-fn]
"An implementation of `transform*` must use `next-fn` to transform
any subvalues of `structure` and then merge those transformed values
back into `structure`. Everything else in `structure` must be unchanged."
))
back into `structure`. Everything else in `structure` must be unchanged."))
(defprotocol Collector
"Do not use this protocol directly. All navigators must be created using

View file

@ -81,8 +81,8 @@
(defn- select-keys-from-transient-map
"Uses select-keys on a transient map."
[m m-keys]
(select-keys m m-keys))
)
(select-keys m m-keys)))
(defnav
^{:doc "Navigates to the specified persistent submap of a transient map."}

View file

@ -6,8 +6,7 @@
(let [ret# (do ~@body)]
(if (identical? ret# ~backup-res)
curr#
ret#
)))
ret#)))
~backup-res
~aseq
))
~aseq))

View file

@ -12,8 +12,8 @@
(select* [this structure next-fn]
(next-fn (constructor structure)))
(transform* [this structure next-fn]
(zip/root (next-fn (constructor structure)))
))
(zip/root (next-fn (constructor structure)))))
(def VECTOR-ZIP (zipper zip/vector-zip))
(def SEQ-ZIP (zipper zip/seq-zip))
@ -34,12 +34,12 @@
(nav []
(select* [this structure next-fn]
(let [ret (znav structure)]
(if ret (next-fn ret))
))
(if ret (next-fn ret))))
(transform* [this structure next-fn]
(let [ret (znav structure)]
(if ret (next-fn ret) structure)
))))
(if ret (next-fn ret) structure)))))
;; (multi-path RIGHT LEFT) will not navigate to the right and left
;; of the currently navigated element because locations aren't stable
@ -69,12 +69,12 @@
inserts (reduce
(fn [z e] (-> z (inserter e) mover))
structure
to-insert
)]
to-insert)]
(if backer
(reduce (fn [z _] (backer z)) inserts to-insert)
inserts)
))
inserts)))
(defnav ^{:doc "Navigate to the empty subsequence directly to the
right of this element."}
@ -82,8 +82,8 @@
(select* [this structure next-fn]
(next-fn []))
(transform* [this structure next-fn]
(inner-insert structure next-fn zip/insert-right zip/right zip/left)
))
(inner-insert structure next-fn zip/insert-right zip/right zip/left)))
(defnav ^{:doc "Navigate to the empty subsequence directly to the
left of this element."}
@ -91,16 +91,16 @@
(select* [this structure next-fn]
(next-fn []))
(transform* [this structure next-fn]
(inner-insert structure next-fn zip/insert-left identity nil)
))
(inner-insert structure next-fn zip/insert-left identity nil)))
(defnav NODE []
(select* [this structure next-fn]
(next-fn (zip/node structure))
)
(next-fn (zip/node structure)))
(transform* [this structure next-fn]
(zip/edit structure next-fn)
))
(zip/edit structure next-fn)))
(defnav ^{:doc "Navigate to the subsequence containing only
the node currently pointed to. This works just
@ -108,13 +108,13 @@
from the structure"}
NODE-SEQ []
(select* [this structure next-fn]
(next-fn [(zip/node structure)])
)
(next-fn [(zip/node structure)]))
(transform* [this structure next-fn]
(let [to-insert (next-fn [(zip/node structure)])
inserted (reduce zip/insert-left structure to-insert)]
(zip/remove inserted)
)))
(zip/remove inserted))))
(declarepath ^{:doc "Navigate the zipper to the first element
in the structure matching predfn. A linear scan
@ -124,8 +124,8 @@
(providepath find-first
(s/if-path [NODE s/pred]
s/STAY
[NEXT (s/params-reset find-first)]
))
[NEXT (s/params-reset find-first)]))
(declarepath ^{:doc "Navigate to every element reachable using calls
to NEXT"}
@ -134,5 +134,4 @@
(providepath NEXT-WALK
(s/stay-then-continue
NEXT
NEXT-WALK
))
NEXT-WALK))

View file

@ -1,8 +1,8 @@
(ns com.rpl.specter.cljs-test-runner
(:require [cljs.test :as test :refer-macros [run-tests]]
[com.rpl.specter.core-test]
[com.rpl.specter.zipper-test]
))
[com.rpl.specter.zipper-test]))
(run-tests 'com.rpl.specter.core-test)
(run-tests 'com.rpl.specter.zipper-test)

File diff suppressed because it is too large Load diff

View file

@ -2,8 +2,8 @@
(:require [clojure.test.check
[generators :as gen]
[properties :as prop]]
[clojure.test]
)
[clojure.test])
(:use [com.rpl.specter.macros :only [select transform]]
[com.rpl.specter :only [select* transform* must-cache-paths!]]))
@ -29,13 +29,12 @@
icfntran# (fn [~@params-decl] (transform ~apath ~transform-fn ~data))
regfnsel# (fn [~@params-decl] (select* ~apath ~data))
regfntran# (fn [~@params-decl] (transform* ~apath ~transform-fn ~data))
params# (if (empty? ~params) [[]] ~params)
]
params# (if (empty? ~params) [[]] ~params)]
(must-cache-paths! ~must-cache?)
(dotimes [_# 3]
(doseq [ps# params#]
(~is-sym (= (apply icfnsel# ps#) (apply regfnsel# ps#)))
(~is-sym (= (apply icfntran# ps#) (apply regfntran# ps#)))
))
(must-cache-paths! false)
)))
(~is-sym (= (apply icfntran# ps#) (apply regfntran# ps#)))))
(must-cache-paths! false))))

View file

@ -5,16 +5,16 @@
[com.rpl.specter.cljs-test-helpers :refer [for-all+]]
[com.rpl.specter.macros
:refer [declarepath providepath select select-one select-one!
select-first transform setval replace-in]]
))
select-first transform setval replace-in]]))
(: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 [declarepath providepath select select-one select-one!
select-first transform setval replace-in]])
)
select-first transform setval replace-in]]))
(:require #?(:clj [clojure.test.check.generators :as gen])
#?(:clj [clojure.test.check.properties :as prop])
#?(:cljs [cljs.test.check :as tc])
@ -28,8 +28,8 @@
[v (gen/not-empty (gen/vector gen/int))
i (gen/vector gen/int)]
(= (setval s/END i v)
(setval [z/VECTOR-ZIP z/DOWN z/RIGHTMOST z/INNER-RIGHT] i v))
))
(setval [z/VECTOR-ZIP z/DOWN z/RIGHTMOST z/INNER-RIGHT] i v))))
(deftest zipper-multi-insert-test
(is (= [1 2 :a :b 3 :a :b 4]
@ -37,22 +37,22 @@
z/DOWN
z/RIGHT
z/RIGHT
(s/multi-path z/INNER-RIGHT z/INNER-LEFT)
]
(s/multi-path z/INNER-RIGHT z/INNER-LEFT)]
[:a :b]
[1 2 3 4]
)
[1 2 3 4])
(setval [z/VECTOR-ZIP
z/DOWN
z/RIGHT
z/RIGHT
(s/multi-path z/INNER-LEFT z/INNER-RIGHT)
]
(s/multi-path z/INNER-LEFT z/INNER-RIGHT)]
[:a :b]
[1 2 3 4]
)
))
)
[1 2 3 4]))))
(deftest zipper-down-up-test
(is (= [1 [2 3 5] 6]
@ -67,9 +67,9 @@
[z/UP z/RIGHT])
z/NODE]
inc
[1 [2 3 4] 5]
)))
)
[1 [2 3 4] 5]))))
(deftest next-terminate-test
@ -83,10 +83,10 @@
(s/selected? z/NODE number? even?)
z/NODE-SEQ]
[]
[1 2 [3 [[4]] 5] 6]
)
))
)
[1 2 [3 [[4]] 5] 6]))))
(deftest zipper-nav-stop-test
(is (= [1]
@ -96,19 +96,19 @@
(is (= [1]
(transform [z/VECTOR-ZIP z/DOWN z/RIGHT z/NODE] inc [1])))
(is (= []
(transform [z/VECTOR-ZIP z/DOWN z/NODE] inc [])))
)
(transform [z/VECTOR-ZIP z/DOWN z/NODE] inc []))))
(deftest find-first-test
(is (= [1 [3 [[4]] 5] 6]
(setval [z/VECTOR-ZIP
(z/find-first #(and (number? %) (even? %)))
z/NODE-SEQ
]
z/NODE-SEQ]
[]
[1 2 [3 [[4]] 5] 6])
))
)
[1 2 [3 [[4]] 5] 6]))))
(deftest nodeseq-expand-test
(is (= [2 [2] [[4 4 4]] 4 4 4 6]
@ -119,6 +119,4 @@
z/NODE-SEQ]
(fn [v _]
(repeat v (inc v)))
[1 [2] [[3]] 3 6]
)))
)
[1 [2] [[3]] 3 6]))))