switch from cljx to cljc

This commit is contained in:
Nathan Marz 2016-08-06 10:40:45 -04:00
parent fb6cd38b1d
commit 74f38d93a9
11 changed files with 269 additions and 267 deletions

View file

@ -3,11 +3,10 @@
(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"
]
]
:source-paths ["src/clj"]
:java-source-paths ["src/java"]
:test-paths ["test", "target/test-classes"]
:jar-exclusions [#"\.cljx"]
:auto-clean false
:dependencies [[riddley "0.1.12"]]
:plugins [[lein-codox "0.9.5"]]
@ -26,25 +25,8 @@
[[org.clojure/test.check "0.7.0"]
[org.clojure/clojure "1.7.0"]
[org.clojure/clojurescript "1.7.10"]]
:plugins
[[com.keminglabs/cljx "0.6.0"]]
:cljx {:builds [{:source-paths ["src/clj"]
:output-path "target/classes"
:rules :clj}
{:source-paths ["src/clj"]
:output-path "target/classes"
:rules :cljs}
{:source-paths ["test"]
:output-path "target/test-classes"
:rules :clj}
{:source-paths ["test"]
:output-path "target/test-classes"
:rules :cljs}]}
}
:test {:dependencies [[org.clojure/clojure "1.7.0"]]}
}
:aliases {"cleantest" ["do" "clean,"
"cljx" "once,"
"test"]
"deploy" ["do" "clean," "cljx" "once," "deploy" "clojars"]}
:aliases {"deploy" ["do" "clean," "deploy" "clojars"]}
)

View file

@ -1,5 +1,5 @@
(ns com.rpl.specter
#+cljs (:require-macros
#?(:cljs (:require-macros
[com.rpl.specter.macros
:refer
[fixed-pathed-collector
@ -12,17 +12,17 @@
]]
[com.rpl.specter.util-macros :refer
[doseqres]]
)
))
(:use [com.rpl.specter.protocols :only [ImplicitNav]]
#+clj [com.rpl.specter.macros :only
[fixed-pathed-collector
fixed-pathed-nav
defcollector
defnav
defpathedfn
richnav
defnavconstructor]]
#+clj [com.rpl.specter.util-macros :only [doseqres]]
#?(:clj [com.rpl.specter.macros :only
[fixed-pathed-collector
fixed-pathed-nav
defcollector
defnav
defpathedfn
richnav
defnavconstructor]])
#?(:clj [com.rpl.specter.util-macros :only [doseqres]])
)
(:require [com.rpl.specter.impl :as i]
[com.rpl.specter.navs :as n]
@ -525,16 +525,16 @@
ImplicitNav
(implicit-nav [this] STAY))
(extend-type #+clj clojure.lang.Keyword #+cljs cljs.core/Keyword
(extend-type #?(:clj clojure.lang.Keyword :cljs cljs.core/Keyword)
ImplicitNav
(implicit-nav [this] (keypath this))
)
(extend-type #+clj clojure.lang.AFn #+cljs function
(extend-type #?(:clj clojure.lang.AFn :cljs function)
ImplicitNav
(implicit-nav [this] (pred this)))
(extend-type #+clj clojure.lang.PersistentHashSet #+cljs cljs.core/PersistentHashSet
(extend-type #?(:clj clojure.lang.PersistentHashSet :cljs cljs.core/PersistentHashSet)
ImplicitNav
(implicit-nav [this] (pred this)))

View file

@ -1,21 +1,18 @@
(ns com.rpl.specter.impl
#+cljs (:require-macros
[com.rpl.specter.prot-opt-invoke
:refer [mk-optimized-invocation]]
#?(:cljs (:require-macros
[com.rpl.specter.defhelpers :refer [define-ParamsNeededPath]]
[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 [com.rpl.specter.defhelpers :as dh])
#?(:clj [riddley.walk :as riddley])
)
#+clj
(:import [com.rpl.specter Util MutableCell])
#?(:clj (:import [com.rpl.specter Util MutableCell]))
)
(def NONE ::NONE)
@ -51,45 +48,53 @@
([a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 & r] v)
))
#+clj
#?(:clj
(defmacro throw* [etype & args]
`(throw (new ~etype (smart-str ~@args))))
`(throw (new ~etype (smart-str ~@args)))))
#+clj
#?(
:clj
(defmacro throw-illegal [& args]
`(throw* IllegalArgumentException ~@args))
#+cljs
:cljs
(defn throw-illegal [& 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
;; namespace does not exist
#+clj
#?(
:clj
(defn cljs-analyzer-macroexpand-1 []
(eval 'cljs.analyzer/macroexpand-1))
;; this version is for bootstrap cljs
#+cljs
:cljs
(defn cljs-analyzer-macroexpand-1 []
^:cljs.analyzer/no-resolve cljs.analyzer/macroexpand-1)
)
#+clj
#?(
:clj
(defn clj-macroexpand-all [form]
(riddley/macroexpand-all form))
#+cljs
:cljs
(defn clj-macroexpand-all [form]
(throw-illegal "not implemented"))
)
#+clj
#?(
:clj
(defn intern* [ns name val] (intern ns name val))
#+cljs
:cljs
(defn intern* [ns name val]
(throw-illegal "intern not supported in ClojureScript"))
)
(defn benchmark [iters afn]
(time
@ -105,45 +110,53 @@
(rich-transform* [this params params-idx vals structure next-fn])
)
#+clj
#?(
:clj
(defmacro exec-rich-select* [this & args]
(let [hinted (with-meta this {:tag 'com.rpl.specter.impl.RichNavigator})]
`(.rich-select* ~hinted ~@args)
))
#+cljs
: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))
)
#+clj
#?(
:clj
(defmacro exec-rich-transform* [this & args]
(let [hinted (with-meta this {:tag 'com.rpl.specter.impl.RichNavigator})]
`(.rich-transform* ~hinted ~@args)
))
#+cljs
: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))
)
#+clj
#?(
:clj
(defmacro exec-select* [this & args]
(let [hinted (with-meta this {:tag 'com.rpl.specter.protocols.Navigator})]
`(.select* ~hinted ~@args)
))
#+cljs
:cljs
(defn exec-select* [this structure next-fn]
(p/select* ^not-native this structure next-fn))
)
#+clj
#?(
:clj
(defmacro exec-transform* [this & args]
(let [hinted (with-meta this {:tag 'com.rpl.specter.protocols.Navigator})]
`(.transform* ~hinted ~@args)
))
#+cljs
:cljs
(defn exec-transform* [this structure next-fn]
(p/transform* ^not-native this structure next-fn))
)
(def RichPathExecutor
(->ExecutorFunctions
@ -194,16 +207,18 @@
(declare bind-params*)
#+clj
#?(
:clj
(defmacro fast-object-array [i]
`(com.rpl.specter.Util/makeObjectArray ~i))
#+cljs
:cljs
(defn fast-object-array [i]
(object-array i))
)
#+clj
#?(
:clj
(dh/define-ParamsNeededPath
true
clojure.lang.IFn
@ -212,7 +227,7 @@
(let [a (object-array args)]
(com.rpl.specter.impl/bind-params* this a 0))))
#+cljs
:cljs
(define-ParamsNeededPath
false
cljs.core/IFn
@ -227,6 +242,7 @@
rest))]
(com.rpl.specter.impl/bind-params* this a 0))
))
)
(defn params-needed-path? [o]
(instance? ParamsNeededPath o))
@ -288,24 +304,24 @@
(coerce-path [this]
this)
#+clj java.util.List #+cljs cljs.core/PersistentVector
#?(:clj java.util.List :cljs cljs.core/PersistentVector)
(coerce-path [this]
(do-comp-paths this))
#+cljs cljs.core/IndexedSeq
#+cljs (coerce-path [this]
(coerce-path (vec this)))
#+cljs cljs.core/EmptyList
#+cljs (coerce-path [this]
(coerce-path (vec this)))
#+cljs cljs.core/List
#+cljs (coerce-path [this]
(coerce-path (vec this)))
#+cljs cljs.core/LazySeq
#+cljs (coerce-path [this]
(coerce-path (vec this)))
#?(:cljs cljs.core/IndexedSeq)
#?(:cljs (coerce-path [this]
(coerce-path (vec this))))
#?(:cljs cljs.core/EmptyList)
#?(:cljs (coerce-path [this]
(coerce-path (vec this))))
#?(:cljs cljs.core/List)
#?(:cljs (coerce-path [this]
(coerce-path (vec this))))
#?(:cljs cljs.core/LazySeq)
#?(:cljs (coerce-path [this]
(coerce-path (vec this))))
#+clj Object #+cljs default
#?(:clj Object :cljs default)
(coerce-path [this]
(coerce-object this)))
@ -388,10 +404,10 @@
nil
(do-comp-paths [o]
(coerce-path o))
#+clj Object #+cljs default
#?(:clj Object :cljs default)
(do-comp-paths [o]
(coerce-path o))
#+clj java.util.List #+cljs cljs.core/PersistentVector
#?(:clj java.util.List :cljs cljs.core/PersistentVector)
(do-comp-paths [navigators]
(if (empty? navigators)
(coerce-path nil)
@ -430,42 +446,50 @@
;; cell implementation idea taken from prismatic schema library
#+cljs
#?(:cljs
(defprotocol PMutableCell
(set_cell [cell x]))
)
#+cljs
#?(:cljs
(deftype MutableCell [^:volatile-mutable q]
PMutableCell
(set_cell [this x] (set! q x)))
)
#+cljs
(defn mutable-cell
([] (mutable-cell nil))
([init] (MutableCell. init)))
#+cljs
(defn set-cell! [cell val]
(set_cell cell val))
#+cljs
(defn get-cell [cell]
#+clj (get_cell cell) #+cljs (.-q cell)
)
#+clj
#?(
:clj
(defn mutable-cell
([] (mutable-cell nil))
([v] (MutableCell. v)))
#+clj
:cljs
(defn mutable-cell
([] (mutable-cell nil))
([init] (MutableCell. init)))
)
#?(
:clj
(defn set-cell! [^MutableCell c v]
(.set c v))
:cljs
(defn set-cell! [cell val]
(set_cell cell val))
)
#?(
:clj
(defn get-cell [^MutableCell c]
(.get c))
#+clj
(defn set-cell! [^MutableCell c v]
(.set c v))
:cljs
(defn get-cell [cell]
(.-q cell))
)
(defn update-cell! [cell afn]
@ -488,7 +512,8 @@
;; amazingly doing this as a macro shows a big effect in the
;; benchmark for getting a value out of a nested map
#+clj
#?(
:clj
(defmacro compiled-traverse* [path result-fn structure]
`(let [nav# (compiled-nav-field ~path)
ex# (compiled-executors-field ~path)]
@ -498,7 +523,7 @@
~structure)
))
#+cljs
:cljs
(defn compiled-traverse* [path result-fn structure]
(let [nav (compiled-nav-field path)
ex (compiled-executors-field path)]
@ -507,13 +532,14 @@
result-fn
structure)
))
)
(defn do-compiled-traverse [apath structure]
(reify #+clj clojure.lang.IReduce #+cljs cljs.core/IReduce
(#+clj reduce #+cljs -reduce
(reify #?(:clj clojure.lang.IReduce :cljs cljs.core/IReduce)
(#?(:clj reduce :cljs -reduce)
[this afn]
(#+clj .reduce #+cljs -reduce this afn (afn)))
(#+clj reduce #+cljs -reduce
(#?(:clj .reduce :cljs -reduce) this afn (afn)))
(#?(:clj reduce :cljs -reduce)
[this afn start]
(let [cell (mutable-cell start)]
(compiled-traverse*
@ -616,9 +642,9 @@
))))
(defn fn-invocation? [f]
(or #+clj (instance? clojure.lang.Cons f)
#+clj (instance? clojure.lang.LazySeq f)
#+cljs (instance? cljs.core.LazySeq f)
(or #?(:clj (instance? clojure.lang.Cons f))
#?(:clj (instance? clojure.lang.LazySeq f))
#?(:cljs (instance? cljs.core.LazySeq f))
(list? f)))
(defrecord LayeredNav [underlying])
@ -702,13 +728,13 @@
(or (satisfies? p/ImplicitNav v)
(instance? CompiledPath v)))
#+cljs
#?(:cljs
(defn handle-params [precompiled params-maker possible-params]
(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)
))
)))
(defn filter-select [afn structure next-fn]
(if (afn structure)
@ -980,11 +1006,12 @@
;; This is needed when aset is used on primitive values in mk-params-maker
;; to avoid reflection
#+clj
#?(:clj
(defn aset-object [^objects a i ^Object v]
(aset a i v))
(aset a i v)))
#+clj
#?(
:clj
(defn mk-params-maker [ns-str params-code possible-params-code used-locals]
(let [ns (find-ns (symbol ns-str))
array-sym (gensym "array")]
@ -1000,13 +1027,14 @@
~array-sym
))))))
#+cljs
:cljs
(defn mk-params-maker [ns-str params-code possible-params-code used-locals]
(let [indexed (->> possible-params-code
(map-indexed (comp vec reverse vector))
(into {}))]
;;TODO: may be more efficient as an array
(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]
@ -1060,7 +1088,7 @@
(defn compiled-multi-transform* [path structure]
(compiled-transform* path multi-transform-error-fn structure))
#+clj
#?(:clj
(defn extend-protocolpath* [protpath protpath-prot extensions]
(let [extensions (partition 2 extensions)
m (-> protpath-prot :sigs keys first)
@ -1074,7 +1102,7 @@
(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)})
))))
)))))
(defn parameterize-path [apath params params-idx]
(if (instance? CompiledPath apath)

View file

@ -1,5 +1,5 @@
(ns com.rpl.specter.navs
#+cljs (:require-macros
#?(:cljs (:require-macros
[com.rpl.specter.macros
:refer
[fixed-pathed-collector
@ -12,12 +12,12 @@
]]
[com.rpl.specter.util-macros :refer
[doseqres]]
)
(:use #+clj [com.rpl.specter macros]
#+clj [com.rpl.specter.util-macros :only [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]
#?(:clj [clojure.core.reducers :as r])
[com.rpl.specter.defnavhelpers] ; so that for cljs it's loaded as macros expand to this
)
)
@ -61,14 +61,16 @@
(doseqres i/NONE [e structure]
(next-fn e)))
#+cljs
(defn queue? [coll]
(= (type coll) (type #queue [])))
#+clj
#?(
:clj
(defn queue? [coll]
(instance? clojure.lang.PersistentQueue coll))
:cljs
(defn queue? [coll]
(= (type coll) (type #queue [])))
)
(defprotocol AllTransformProtocol
(all-transform [structure next-fn]))
@ -89,21 +91,20 @@
)
;; in cljs they're PersistentVector so don't need a special case
#+clj clojure.lang.MapEntry
#+clj
#?(:clj clojure.lang.MapEntry)
#?(:clj
(all-transform [structure next-fn]
(let [newk (next-fn (key structure))
newv (next-fn (val structure))]
(clojure.lang.MapEntry. newk newv)
))
)))
#+clj clojure.lang.PersistentVector #+cljs cljs.core/PersistentVector
#?(:clj clojure.lang.PersistentVector :cljs cljs.core/PersistentVector)
(all-transform [structure next-fn]
(mapv next-fn structure))
#+clj
clojure.lang.PersistentArrayMap
#+clj
#?(:clj clojure.lang.PersistentArrayMap)
#?(:clj
(all-transform [structure next-fn]
(let [k-it (.keyIterator structure)
v-it (.valIterator structure)]
@ -114,21 +115,20 @@
[newk newv] (next-fn [k v])]
(recur (assoc ret newk newv)))
ret
))))
)))))
#+cljs
cljs.core/PersistentArrayMap
#+cljs
#?(:cljs cljs.core/PersistentArrayMap)
#?(:cljs
(all-transform [structure next-fn]
(non-transient-map-all-transform structure next-fn {})
)
))
#+clj clojure.lang.PersistentTreeMap #+cljs cljs.core/PersistentTreeMap
#?(:clj clojure.lang.PersistentTreeMap :cljs cljs.core/PersistentTreeMap)
(all-transform [structure next-fn]
(non-transient-map-all-transform structure next-fn (empty structure))
)
#+clj clojure.lang.PersistentHashMap #+cljs cljs.core/PersistentHashMap
#?(:clj clojure.lang.PersistentHashMap :cljs cljs.core/PersistentHashMap)
(all-transform [structure next-fn]
(persistent!
(reduce-kv
@ -137,15 +137,14 @@
(assoc! m newk newv)
))
(transient
#+clj clojure.lang.PersistentHashMap/EMPTY #+cljs cljs.core.PersistentHashMap.EMPTY
#?(:clj clojure.lang.PersistentHashMap/EMPTY :cljs cljs.core.PersistentHashMap.EMPTY)
)
structure
)))
#+clj
Object
#+clj
#?(:clj Object)
#?(:clj
(all-transform [structure next-fn]
(let [empty-structure (empty structure)]
(cond (and (list? empty-structure) (not (queue? empty-structure)))
@ -165,18 +164,17 @@
:else
(->> structure (r/map next-fn) (into empty-structure))
)))
))))
#+cljs
default
#+cljs
#?(:cljs default)
#?(:cljs
(all-transform [structure next-fn]
(let [empty-structure (empty structure)]
(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)
)))
))))
)
(defprotocol MapValsTransformProtocol
@ -195,9 +193,8 @@
nil
)
#+clj
clojure.lang.PersistentArrayMap
#+clj
#?(:clj clojure.lang.PersistentArrayMap)
#?(:clj
(map-vals-transform [structure next-fn]
(let [k-it (.keyIterator structure)
v-it (.valIterator structure)]
@ -207,33 +204,32 @@
v (.next v-it)]
(recur (assoc ret k (next-fn v))))
ret
))))
)))))
#+cljs
cljs.core/PersistentArrayMap
#+cljs
#?(:cljs cljs.core/PersistentArrayMap)
#?(:cljs
(map-vals-transform [structure next-fn]
(map-vals-non-transient-transform structure {} next-fn)
)
))
#+clj clojure.lang.PersistentTreeMap #+cljs cljs.core/PersistentTreeMap
#?(:clj clojure.lang.PersistentTreeMap :cljs cljs.core/PersistentTreeMap)
(map-vals-transform [structure next-fn]
(map-vals-non-transient-transform structure (empty structure) next-fn)
)
#+clj clojure.lang.PersistentHashMap #+cljs cljs.core/PersistentHashMap
#?(:clj clojure.lang.PersistentHashMap :cljs cljs.core/PersistentHashMap)
(map-vals-transform [structure next-fn]
(persistent!
(reduce-kv
(fn [m k v]
(assoc! m k (next-fn v)))
(transient
#+clj clojure.lang.PersistentHashMap/EMPTY #+cljs cljs.core.PersistentHashMap.EMPTY
#?(:clj clojure.lang.PersistentHashMap/EMPTY :cljs cljs.core.PersistentHashMap.EMPTY)
)
structure
)))
#+clj Object #+cljs default
#?(:clj Object :cljs default)
(map-vals-transform [structure next-fn]
(reduce-kv
(fn [m k v]
@ -334,7 +330,7 @@
(prepend-all [_ elements]
elements)
#+clj clojure.lang.PersistentVector #+cljs cljs.core/PersistentVector
#?(:clj clojure.lang.PersistentVector :cljs cljs.core/PersistentVector)
(append-all [structure elements]
(reduce conj structure elements))
(prepend-all [structure elements]
@ -345,7 +341,7 @@
(persistent! <>)
)))
#+clj Object #+cljs default
#?(:clj Object :cljs default)
(append-all [structure elements]
(concat structure elements))
(prepend-all [structure elements]
@ -380,24 +376,28 @@
(defn- update-last-list [l afn]
(append (butlast l) (afn (last l))))
#+clj
#?(
:clj
(defn vec-count [^clojure.lang.IPersistentVector v]
(.length v))
#+cljs
:cljs
(defn vec-count [v]
(count v))
)
#+clj
#?(
:clj
(defn transient-vec-count [^clojure.lang.ITransientVector v]
(.count v))
#+cljs
:cljs
(defn transient-vec-count [v]
(count v))
)
(extend-protocol UpdateExtremes
#+clj clojure.lang.PersistentVector #+cljs cljs.core/PersistentVector
#?(:clj clojure.lang.PersistentVector :cljs cljs.core/PersistentVector)
(update-first [v afn]
(let [val (nth v 0)]
(assoc v 0 (afn val))
@ -411,7 +411,7 @@
(let [i (dec c)]
(assoc v i (afn (nth v i)))
))))
#+clj Object #+cljs default
#?(:clj Object :cljs default)
(update-first [l val]
(update-first-list l val))
(update-last [l val]
@ -419,12 +419,12 @@
))
(extend-protocol GetExtremes
#+clj clojure.lang.IPersistentVector #+cljs cljs.core/PersistentVector
#?(:clj clojure.lang.IPersistentVector :cljs cljs.core/PersistentVector)
(get-first [v]
(nth v 0))
(get-last [v]
(peek v))
#+clj Object #+cljs default
#?(:clj Object :cljs default)
(get-first [s]
(first s))
(get-last [s]
@ -436,13 +436,13 @@
nil
(fast-empty? [_] true)
#+clj clojure.lang.IPersistentVector #+cljs cljs.core/PersistentVector
#?(:clj clojure.lang.IPersistentVector :cljs cljs.core/PersistentVector)
(fast-empty? [v]
(= 0 (vec-count v)))
#+clj clojure.lang.ITransientVector #+cljs cljs.core/TransientVector
#?(:clj clojure.lang.ITransientVector :cljs cljs.core/TransientVector)
(fast-empty? [v]
(= 0 (transient-vec-count v)))
#+clj Object #+cljs default
#?(:clj Object :cljs default)
(fast-empty? [s]
(empty? s))
)

View file

@ -1,11 +0,0 @@
(ns com.rpl.specter.prot-opt-invoke)
(defmacro mk-optimized-invocation [protocol obj method num-args]
(let [args (take num-args (repeatedly gensym))
o (-> (gensym) (with-meta {:tag 'not-native}))]
`(if (~'implements? ~protocol ~obj)
(fn [~o ~@args]
(~method ~o ~@args)
)
~method
)))

View file

@ -1,13 +1,13 @@
(ns com.rpl.specter.transients
#+cljs
#?(:cljs
(:require-macros [com.rpl.specter.macros
:refer
[defnav
defpathedfn]])
(:use #+clj
defpathedfn]]))
(:use #?(:clj
[com.rpl.specter.macros :only
[defnav
defpathedfn]])
defpathedfn]]))
(:require [com.rpl.specter.navs :as n]
[com.rpl.specter :refer [subselect selected?]]))
@ -59,7 +59,8 @@
"Navigates to the last element of a transient vector."
(n/PosNavigator t-get-last t-update-last))
#+clj
#?(
:clj
(defn- select-keys-from-transient-map
"Selects keys from transient map, because built-in select-keys uses
`find` which is unsupported."
@ -76,11 +77,12 @@
result)
(rest m-keys))))))
#+cljs
:cljs
(defn- select-keys-from-transient-map
"Uses select-keys on a transient map."
[m m-keys]
(select-keys m m-keys))
)
(defnav
^{:doc "Navigates to the specified persistent submap of a transient map."}

View file

@ -1,10 +1,10 @@
(ns com.rpl.specter.zipper
#+cljs (:require-macros
#?(:cljs (:require-macros
[com.rpl.specter.macros
:refer [defnav nav declarepath providepath]])
#+clj
:refer [defnav nav declarepath providepath]]))
#?(:clj
(:use
[com.rpl.specter.macros :only [defnav nav declarepath providepath]])
[com.rpl.specter.macros :only [defnav nav declarepath providepath]]))
(:require [com.rpl.specter :as s]
[clojure.zip :as zip]))
@ -43,9 +43,9 @@
;; (multi-path RIGHT LEFT) will not navigate to the right and left
;; of the currently navigated element because locations aren't stable
;; like they are for maps/graphs. The path following RIGHT could
;; like they are for maps/graphs. The path following RIGHT could
;; insert lots of elements all over the sequence, and there's no
;; way to determine how to get "back".
;; way to determine how to get "back".
(def ^{:doc "Navigate to the element to the right.
If no element there, works like STOP."}
RIGHT (mk-zip-nav zip/right))
@ -103,7 +103,7 @@
))
(defnav ^{:doc "Navigate to the subsequence containing only
the node currently pointed to. This works just
the node currently pointed to. This works just
like srange and can be used to remove elements
from the structure"}
NODE-SEQ []

View file

@ -1,5 +1,5 @@
(ns com.rpl.specter.core-test
#+cljs (:require-macros
#?(:cljs (:require-macros
[cljs.test :refer [is deftest]]
[cljs.test.check.cljs-test :refer [defspec]]
[com.rpl.specter.cljs-test-helpers :refer [for-all+]]
@ -9,25 +9,25 @@
nav declarepath providepath select select-one select-one!
select-first transform setval replace-in defnavconstructor
select-any selected-any? collected? traverse
multi-transform]])
multi-transform]]))
(:use
#+clj [clojure.test :only [deftest is]]
#+clj [clojure.test.check.clojure-test :only [defspec]]
#+clj [com.rpl.specter.test-helpers :only [for-all+ ic-test]]
#+clj [com.rpl.specter.macros
:only [paramsfn defprotocolpath defnav extend-protocolpath
nav declarepath providepath select select-one select-one!
select-first transform setval replace-in defnavconstructor
select-any selected-any? collected? traverse
multi-transform]]
#?(:clj [clojure.test :only [deftest is]])
#?(:clj [clojure.test.check.clojure-test :only [defspec]])
#?(:clj [com.rpl.specter.test-helpers :only [for-all+ ic-test]])
#?(:clj [com.rpl.specter.macros
:only [paramsfn defprotocolpath defnav extend-protocolpath
nav declarepath providepath select select-one select-one!
select-first transform setval replace-in defnavconstructor
select-any selected-any? collected? traverse
multi-transform]])
)
(:require #+clj [clojure.test.check.generators :as gen]
#+clj [clojure.test.check.properties :as prop]
#+cljs [cljs.test.check :as tc]
#+cljs [cljs.test.check.generators :as gen]
#+cljs [cljs.test.check.properties :as prop :include-macros true]
(:require #?(:clj [clojure.test.check.generators :as gen])
#?(:clj [clojure.test.check.properties :as prop])
#?(:cljs [cljs.test.check :as tc])
#?(:cljs [cljs.test.check.generators :as gen])
#?(:cljs [cljs.test.check.properties :as prop :include-macros true])
[com.rpl.specter :as s]
[com.rpl.specter.transients :as t]
[clojure.set :as set]))
@ -76,7 +76,7 @@
))
(deftest select-one-test
(is (thrown? #+clj Exception #+cljs js/Error (select-one [s/ALL even?] [1 2 3 4])))
(is (thrown? #?(:clj Exception :cljs js/Error) (select-one [s/ALL even?] [1 2 3 4])))
(is (= 1 (select-one [s/ALL odd?] [2 4 1 6])))
)
@ -247,7 +247,7 @@
(deftest atom-test
(let [v (transform s/ATOM inc (atom 1))]
(is (instance? #+clj clojure.lang.Atom #+cljs cljs.core/Atom v))
(is (instance? #?(:clj clojure.lang.Atom :cljs cljs.core/Atom) v))
(is (= 2 (select-one s/ATOM v) @v))))
(defspec view-test
@ -453,7 +453,7 @@
(deftest nil-select-one-test
(is (= nil (select-one! s/ALL [nil])))
(is (thrown? #+clj Exception #+cljs js/Error (select-one! s/ALL [])))
(is (thrown? #?(:clj Exception :cljs js/Error) (select-one! s/ALL [])))
)
@ -756,7 +756,7 @@
[:q [:abc 3] [:ccc [:abc] [:abc "a" [:abc [:abc [:d]]]]]]
))))
#+clj
#?(:clj
(deftest large-params-test
(let [path (apply s/comp-paths (repeat 25 s/keypath))
m (reduce
@ -765,20 +765,20 @@
:a
(reverse (range 25)))]
(is (= :a (select-one (apply path (range 25)) m)))
))
)))
;;TODO: there's a bug in clojurescript that won't allow
;; non function implementations of IFn to have more than 20 arguments
#+clj
#?(:clj
(do
(defprotocolpath AccountPath [])
(defrecord Account [funds])
(defrecord User [account])
(defrecord Family [accounts])
(extend-protocolpath AccountPath User :account Family [:accounts s/ALL])
)
))
#+clj
#?(:clj
(deftest protocolpath-basic-test
(let [data [(->User (->Account 30))
(->User (->Account 50))
@ -791,9 +791,9 @@
(transform [s/ALL AccountPath :funds]
inc
data)))
))
)))
#+clj
#?(:clj
(do
(defprotocolpath LabeledAccountPath [label])
(defrecord LabeledUser [account])
@ -801,9 +801,9 @@
(extend-protocolpath LabeledAccountPath
LabeledUser [:account s/keypath]
LabeledFamily [:accounts s/keypath s/ALL])
)
))
#+clj
#?(:clj
(deftest protocolpath-params-test
(let [data [(->LabeledUser {:a (->Account 30)})
(->LabeledUser {:a (->Account 50)})
@ -816,10 +816,10 @@
(transform [s/ALL (LabeledAccountPath :a) :funds]
inc
data)))
))
)))
#+clj
#?(:clj
(do
(defprotocolpath CustomWalker [])
(extend-protocolpath CustomWalker
@ -827,32 +827,33 @@
clojure.lang.PersistentHashMap [(s/keypath :a) CustomWalker]
clojure.lang.PersistentArrayMap [(s/keypath :a) CustomWalker]
clojure.lang.PersistentVector [s/ALL CustomWalker]
)
)))
)
#+clj
#?(:clj
(deftest mixed-rich-regular-protocolpath
(is (= [1 2 3 11 21 22 25]
(select [CustomWalker number?] [{:a [1 2 :c [3]]} [[[[[[11]]] 21 [22 :c 25]]]]])))
(is (= [2 3 [[[4]] :b 0] {:a 4 :b 10}]
(transform [CustomWalker number?] inc [1 2 [[[3]] :b -1] {:a 3 :b 10}])))
)
))
#+cljs
(defn make-queue [coll]
(reduce
#(conj %1 %2)
#queue []
coll))
#+clj
#?(
:clj
(defn make-queue [coll]
(reduce
#(conj %1 %2)
clojure.lang.PersistentQueue/EMPTY
coll))
:cljs
(defn make-queue [coll]
(reduce
#(conj %1 %2)
#queue []
coll))
)
(defspec transform-idempotency 50
(for-all+
[v1 (gen/vector gen/int)
@ -964,26 +965,26 @@
)
(s/must-cache-paths!)
(is (thrown? #+clj Exception #+cljs js/Error
(is (thrown? #?(:clj Exception :cljs js/Error)
(select (if true :a :b) nil)
))
(is (thrown? #+clj Exception #+cljs js/Error
(is (thrown? #?(:clj Exception :cljs js/Error)
(select (*APATH* :a) nil)
))
(is (thrown? #+clj Exception #+cljs js/Error
(is (thrown? #?(:clj Exception :cljs js/Error)
(select [:a (identity even?)] {:a 2})
))
;; this tests a bug that existed before ^:staticparam annotation
;; for pathedfns
(is (thrown? #+clj Exception #+cljs js/Error
(is (thrown? #?(:clj Exception :cljs js/Error)
(select [(s/putval 10) (s/transformed s/STAY #(inc %))] 10)
))
(let [p :a]
(is (thrown? #+clj Exception #+cljs js/Error
(is (thrown? #?(:clj Exception :cljs js/Error)
(select [p even?] {:a 2})
)))
(let [p :a]
(is (thrown? #+clj Exception #+cljs js/Error
(is (thrown? #?(:clj Exception :cljs js/Error)
(select [s/ALL (s/selected? p even?)] [{:a 2}])
)))
(s/must-cache-paths! false)
@ -1036,13 +1037,13 @@
(is (= false (select-one! (s/nil->val true) false)))
)
#+clj
#?(:clj
(deftest all-map-entry
(let [e (transform s/ALL inc (first {1 3}))]
(is (instance? clojure.lang.MapEntry e))
(is (= 2 (key e)))
(is (= 4 (val e)))
))
)))
(deftest select-on-empty-vector
(is (= s/NONE (select-any s/ALL [])))
@ -1320,7 +1321,7 @@
))))
(deftest multi-transform-overrun-error
(is (thrown? #+clj Exception #+cljs js/Error (multi-transform s/STAY 3)))
(is (thrown? #?(:clj Exception :cljs js/Error) (multi-transform s/STAY 3)))
)
(deftest terminal-val-test

View file

@ -1,25 +1,25 @@
(ns com.rpl.specter.zipper-test
#+cljs (:require-macros
#?(:cljs (:require-macros
[cljs.test :refer [is deftest]]
[cljs.test.check.cljs-test :refer [defspec]]
[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]]
)
))
(: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]]
#?(: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]])
)
(:require #+clj [clojure.test.check.generators :as gen]
#+clj [clojure.test.check.properties :as prop]
#+cljs [cljs.test.check :as tc]
#+cljs [cljs.test.check.generators :as gen]
#+cljs [cljs.test.check.properties :as prop :include-macros true]
(:require #?(:clj [clojure.test.check.generators :as gen])
#?(:clj [clojure.test.check.properties :as prop])
#?(:cljs [cljs.test.check :as tc])
#?(:cljs [cljs.test.check.generators :as gen])
#?(:cljs [cljs.test.check.properties :as prop :include-macros true])
[com.rpl.specter :as s]
[com.rpl.specter.zipper :as z]))