Compare commits

...

2 commits

7 changed files with 177 additions and 105 deletions

View file

@ -1,8 +1,8 @@
(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"]

View file

@ -175,9 +175,9 @@
needed (i/num-needed-params params-path)]
(richnav 0
(select* [this params params-idx vals structure next-fn]
(i/exec-rich-select* nav params (- params-idx needed) 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
@ -328,6 +328,7 @@
In a transform, that subset in the original set is changed to the
new value of the subset."}
subset
{:inline-next-fn true}
[aset]
(select* [this structure next-fn]
(next-fn (set/intersection structure aset)))
@ -344,6 +345,7 @@
In a transform, that submap in the original map is changed to the new
value of the submap."}
submap
{:inline-next-fn true}
[m-keys]
(select* [this structure next-fn]
(next-fn (select-keys structure m-keys)))
@ -371,7 +373,7 @@
(select* [this structure next-fn]
(n/walk-select afn next-fn structure))
(transform* [this structure next-fn]
(n/codewalk-until afn next-fn structure)))
(i/codewalk-until afn next-fn structure)))
(defpathedfn subselect
"Navigates to a sequence that contains the results of (select ...),
@ -397,6 +399,7 @@
(defnav
^{:doc "Navigates to the specified key, navigating to nil if it does not exist."}
keypath
{:inline-next-fn true}
[key]
(select* [this structure next-fn]
(next-fn (get structure key)))
@ -407,6 +410,7 @@
(defnav
^{:doc "Navigates to the key only if it exists in the map."}
must
{:inline-next-fn true}
[k]
(select* [this structure next-fn]
(if (contains? structure k)
@ -421,6 +425,7 @@
(defnav
^{:doc "Navigates to result of running `afn` on the currently navigated value."}
view
{:inline-next-fn true}
[afn]
(select* [this structure next-fn]
(next-fn (afn structure)))
@ -433,6 +438,7 @@
transforms, the transformed value then has `unparse-fn` run on
it to get the final value at this point."}
parser
{:inline-next-fn true}
[parse-fn unparse-fn]
(select* [this structure next-fn]
(next-fn (parse-fn structure)))
@ -518,6 +524,7 @@
^{:doc "Keeps the element only if it matches the supplied predicate. This is the
late-bound parameterized version of using a function directly in a path."}
pred
{:inline-next-fn true}
[afn]
(select* [this structure next-fn]
(if (afn structure) (next-fn structure) NONE))
@ -546,6 +553,7 @@
^{:doc "Navigates to the provided val if the structure is nil. Otherwise it stays
navigated at the structure."}
nil->val
{:inline-next-fn true}
[v]
(select* [this structure next-fn]
(next-fn (if (nil? structure) v structure)))
@ -717,15 +725,15 @@
(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)]
(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)))
(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))))))
(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))))))
([path1 path2 & paths]
(reduce multi-path (multi-path path1 path2) paths)))

View file

@ -1,13 +1,13 @@
(ns com.rpl.specter.defnavhelpers
(:require [com.rpl.specter.impl :as i]))
(defn param-delta [i]
(fn [^objects params params-idx]
(defn param-delta [^long i]
(fn [^objects params ^long params-idx]
(aget params (+ params-idx i))))
(defn bound-params [path start-delta]
(fn [^objects params params-idx]
(defn bound-params [path ^long start-delta]
(fn [^objects params ^long params-idx]
(if (i/params-needed-path? path)
(i/bind-params* path params (+ params-idx start-delta))
path)))

View file

@ -1,14 +1,15 @@
(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 definterface+]]))
(: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 definterface+]]))
(:require [com.rpl.specter.protocols :as p]
[clojure.string :as s]
[clojure.walk :as walk]
#?(:clj [com.rpl.specter.defhelpers :as dh])
#?(:clj [riddley.walk :as riddley]))
@ -103,35 +104,35 @@
(deftype ExecutorFunctions [traverse-executor transform-executor])
(deftype ParameterizedRichNav [rich-nav params params-idx])
(deftype ParameterizedRichNav [rich-nav params ^long params-idx])
(defprotocol RichNavigator
(rich-select* [this params params-idx vals structure next-fn])
(rich-transform* [this params params-idx vals structure next-fn]))
(definterface+ RichNavigator
(rich_select [this params ^long params-idx vals structure next-fn])
(rich_transform [this params ^long params-idx vals structure next-fn]))
#?(
:clj
(defmacro exec-rich-select* [this & args]
(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)))
(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
(defmacro exec-rich-transform* [this & args]
(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)))
(defn exec-rich_transform [this params params-idx vals structure next-fn]
(rich_transform ^not-native this params params-idx vals structure next-fn)))
#?(
@ -161,7 +162,7 @@
(def RichPathExecutor
(->ExecutorFunctions
(fn [^ParameterizedRichNav richnavp result-fn structure]
(exec-rich-select* (.-rich-nav richnavp)
(exec-rich_select (.-rich-nav richnavp)
(.-params richnavp) (.-params-idx richnavp)
[] structure
(fn [_ _ vals structure]
@ -170,7 +171,7 @@
structure
(conj vals structure))))))
(fn [^ParameterizedRichNav richnavp transform-fn structure]
(exec-rich-transform* (.-rich-nav richnavp)
(exec-rich_transform (.-rich-nav richnavp)
(.-params richnavp) (.-params-idx richnavp)
[] structure
(fn [_ _ vals structure]
@ -325,22 +326,30 @@
(coerce-path [this]
(coerce-object this)))
#?(:clj
(defn rich-nav? [o]
(instance? RichNavigator o))
:cljs
(defn rich-nav? [o]
(satisfies? RichNavigator o)))
(defn- combine-same-types [[n & _ :as all]]
(let [combiner
(if (satisfies? RichNavigator n)
(if (rich-nav? n)
(fn [curr next]
(reify RichNavigator
(rich-select* [this params params-idx vals structure next-fn]
(exec-rich-select* curr params params-idx vals structure
(rich_select [this params params-idx vals structure next-fn]
(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
(exec-rich_select next params-next params-idx-next
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
(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
(exec-rich_transform next params-next params-idx-next
vals-next structure-next next-fn))))))
(fn [curr next]
@ -356,13 +365,13 @@
(reduce combiner all)))
(defn coerce-rich-navigator [nav]
(if (satisfies? RichNavigator nav)
(if (rich-nav? nav)
nav
(reify RichNavigator
(rich-select* [this params params-idx vals structure next-fn]
(rich_select [this params params-idx vals structure next-fn]
(exec-select* nav structure (fn [structure] (next-fn params params-idx vals structure))))
(rich-transform* [this params params-idx vals structure next-fn]
(rich_transform [this params params-idx vals structure next-fn]
(exec-transform* nav structure (fn [structure] (next-fn params params-idx vals structure)))))))
@ -386,13 +395,13 @@
path
(no-params-rich-compiled-path
(reify RichNavigator
(rich-select* [this params2 params-idx2 vals structure next-fn]
(exec-rich-select* rich-nav params params-idx vals structure
(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))))
(rich-transform* [this params2 params-idx2 vals structure next-fn]
(exec-rich-transform* rich-nav params params-idx vals structure
(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))))))))))
@ -401,7 +410,7 @@
(capture-params-internally (comp-paths* path)))
(defn nav-type [n]
(if (satisfies? RichNavigator n)
(if (rich-nav? n)
:rich
:lean))
@ -652,6 +661,14 @@
#?(:cljs (instance? cljs.core.LazySeq f))
(list? f)))
(defn codewalk-until [pred on-match-fn structure]
(if (pred structure)
(on-match-fn structure)
(let [ret (walk/walk (partial codewalk-until pred on-match-fn) identity structure)]
(if (and (fn-invocation? structure) (fn-invocation? ret))
(with-meta ret (meta structure))
ret))))
(defrecord LayeredNav [underlying])
(defn layered-nav? [o] (instance? LayeredNav o))
@ -766,13 +783,13 @@
(def pred*
(->ParamsNeededPath
(reify RichNavigator
(rich-select* [this params params-idx vals structure next-fn]
(rich_select [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)
NONE)))
(rich-transform* [this params params-idx vals structure next-fn]
(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)
@ -784,13 +801,13 @@
(def collected?*
(->ParamsNeededPath
(reify RichNavigator
(rich-select* [this params params-idx vals structure next-fn]
(rich_select [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)
NONE)))
(rich-transform* [this params params-idx vals structure next-fn]
(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)
@ -802,11 +819,11 @@
(def rich-compiled-path-proxy
(->ParamsNeededPath
(reify RichNavigator
(rich-select* [this params params-idx vals structure next-fn]
(rich_select [this params params-idx vals structure next-fn]
(let [apath ^CompiledPath (aget ^objects params params-idx)
pnav ^ParameterizedRichNav (.-nav apath)
nav (.-rich-nav pnav)]
(exec-rich-select*
(exec-rich_select
nav
(.-params pnav)
(.-params-idx pnav)
@ -815,11 +832,11 @@
(fn [_ _ vals-next structure-next]
(next-fn params params-idx vals-next structure-next)))))
(rich-transform* [this params params-idx vals structure next-fn]
(rich_transform [this params params-idx vals structure next-fn]
(let [apath ^CompiledPath (aget ^objects params params-idx)
pnav ^ParameterizedRichNav (.-nav apath)
nav (.-rich-nav pnav)]
(exec-rich-transform*
(exec-rich_transform
nav
(.-params pnav)
(.-params-idx pnav)
@ -834,7 +851,7 @@
(def lean-compiled-path-proxy
(->ParamsNeededPath
(reify RichNavigator
(rich-select* [this params params-idx vals structure next-fn]
(rich_select [this params params-idx vals structure next-fn]
(let [^CompiledPath apath (aget ^objects params params-idx)
^Navigator nav (.-nav apath)]
(exec-select*
@ -843,7 +860,7 @@
(fn [structure-next]
(next-fn params params-idx vals structure-next)))))
(rich-transform* [this params params-idx vals structure next-fn]
(rich_transform [this params params-idx vals structure next-fn]
(let [^CompiledPath apath (aget ^objects params params-idx)
^Navigator nav (.-nav apath)]
(exec-transform*

View file

@ -1,9 +1,9 @@
(ns com.rpl.specter.macros
(:use [com.rpl.specter.protocols :only [Navigator]]
[com.rpl.specter.impl :only [RichNavigator]])
(:use [com.rpl.specter.protocols :only [Navigator]])
(:require [com.rpl.specter.impl :as i]
[clojure.walk :as cljwalk]
[com.rpl.specter.defnavhelpers :as dnh]))
[com.rpl.specter.defnavhelpers :as dnh])
(:import [com.rpl.specter.impl RichNavigator]))
(defn ^:no-doc gensyms [amt]
@ -34,10 +34,10 @@
`(let [num-params# ~num-params
nav# (reify RichNavigator
(~'rich-select* ~s-params
(~'rich_select ~s-params
(let [~s-next-fn-sym (i/mk-jump-next-fn ~s-next-fn-sym ~s-pidx-sym num-params#)]
~@s-body))
(~'rich-transform* ~t-params
(~'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)))]
@ -62,20 +62,20 @@
`(let [~@binding-fn-declarations]
~body)))
(defmacro ^:no-doc rich-nav-with-bindings [num-params-code bindings & impls]
(defn- rich-nav-with-bindings-not-inlined [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")]
(operation-with-bindings
bindings
params-sym
params-idx-sym
(fn [binding-declarations]
`(reify RichNavigator
(~'rich-select* [this# ~params-sym ~params-idx-sym vals# ~s-structure-sym next-fn#]
(~'rich_select [this# ~params-sym ~params-idx-sym vals# ~s-structure-sym next-fn#]
(let [~@binding-declarations
next-params-idx# (+ ~params-idx-sym ~num-params-code)
~s-next-fn-sym (fn [structure#]
@ -85,7 +85,7 @@
structure#))]
~@s-body))
(~'rich-transform* [this# ~params-sym ~params-idx-sym vals# ~t-structure-sym next-fn#]
(~'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)
~t-next-fn-sym (fn [structure#]
@ -95,6 +95,44 @@
structure#))]
~@t-body)))))))
(defn inline-next-fn [body next-fn-sym extra-params]
(i/codewalk-until
#(and (i/fn-invocation? %) (= next-fn-sym (first %)))
(fn [code]
(let [code (map #(inline-next-fn % next-fn-sym extra-params) code)]
(concat [next-fn-sym] extra-params (rest code))))
body))
(defn- rich-nav-with-bindings-inlined [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")
vals-sym (gensym "vals")
next-params-idx-sym (gensym "next-params-idx")
s-body (inline-next-fn s-body s-next-fn-sym [params-sym next-params-idx-sym vals-sym])
t-body (inline-next-fn t-body t-next-fn-sym [params-sym next-params-idx-sym vals-sym])]
(operation-with-bindings
bindings
params-sym
params-idx-sym
(fn [binding-declarations]
`(reify RichNavigator
(~'rich_select [this# ~params-sym ~params-idx-sym ~vals-sym ~s-structure-sym ~s-next-fn-sym]
(let [~@binding-declarations
~next-params-idx-sym (+ ~params-idx-sym ~num-params-code)]
~@s-body))
(~'rich_transform [this# ~params-sym ~params-idx-sym ~vals-sym ~t-structure-sym ~t-next-fn-sym]
(let [~@binding-declarations
~next-params-idx-sym (+ ~params-idx-sym ~num-params-code)]
~@t-body)))))))
(defmacro ^:no-doc rich-nav-with-bindings [opts num-params-code bindings & impls]
(if (:inline-next-fn opts)
(rich-nav-with-bindings-inlined num-params-code bindings impls)
(rich-nav-with-bindings-not-inlined num-params-code bindings impls)))
(defmacro ^:no-doc collector-with-bindings [num-params-code bindings impl]
@ -112,9 +150,9 @@
(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#]
(~'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#]
(~'rich_transform [this# params# params-idx# vals# structure# next-fn#]
(cfn# params# params-idx# vals# structure# next-fn#))))))))
@ -130,21 +168,25 @@
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 & impls]
(if (empty? params)
`(i/lean-compiled-path (lean-nav* ~@impls))
`(vary-meta
(fn ~params (i/lean-compiled-path (lean-nav* ~@impls)))
assoc
:highernav
{:type :lean
:params-needed-path
(i/->ParamsNeededPath
(rich-nav-with-bindings ~(count params)
~(delta-param-bindings params)
~@impls)
[& impl]
(let [[opts params & impls] (if (map? (first impl))
impl
(cons {} impl))]
(if (empty? params)
`(i/lean-compiled-path (lean-nav* ~@impls))
`(vary-meta
(fn ~params (i/lean-compiled-path (lean-nav* ~@impls)))
assoc
:highernav
{:type :lean
:params-needed-path
(i/->ParamsNeededPath
(rich-nav-with-bindings ~opts
~(count params)
~(delta-param-bindings params)
~@impls)
~(count params))})))
~(count params))}))))
(defmacro collector
@ -214,7 +256,8 @@
(i/lean-compiled-path (lean-nav* ~@impls)))
(i/->ParamsNeededPath
(rich-nav-with-bindings ~total-params-sym
(rich-nav-with-bindings {}
~total-params-sym
~runtime-bindings
~@impls)
@ -297,13 +340,13 @@
`(do
(defprotocol ~prot-name (~m [structure#]))
(let [nav# (reify RichNavigator
(~'rich-select* [this# ~@rargs]
(~'rich_select [this# ~@rargs]
(let [inav# ~retrieve]
(i/exec-rich-select* inav# ~@rargs)))
(i/exec-rich_select inav# ~@rargs)))
(~'rich-transform* [this# ~@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)
@ -325,11 +368,11 @@
([name params]
(let [platform (if (contains? &env :locals) :cljs :clj)
select-exec (if (= platform :clj)
`i/exec-rich-select*
`i/rich-select*)
`i/exec-rich_select
`i/rich_select)
transform-exec (if (= platform :clj)
`i/exec-rich-transform*
`i/rich-transform*)
`i/exec-rich_transform
`i/rich_transform)
num-params (count params)
declared (declared-name name)
rargs [(gensym "params") (gensym "pidx") (gensym "vals")
@ -338,9 +381,9 @@
(declare ~declared)
(def ~name
(let [nav# (reify RichNavigator
(~'rich-select* [this# ~@rargs]
(~'rich_select [this# ~@rargs]
(~select-exec ~declared ~@rargs))
(~'rich-transform* [this# ~@rargs]
(~'rich_transform [this# ~@rargs]
(~transform-exec ~declared ~@rargs)))]
(if (= ~num-params 0)

View file

@ -14,11 +14,14 @@
[doseqres]]))
(:use #?(:clj [com.rpl.specter macros])
#?(:clj [com.rpl.specter.util-macros :only [doseqres]]))
#?(:clj [com.rpl.specter.util-macros :only [doseqres]])
#?(:cljs [com.rpl.specter.impl :only [RichNavigator]]))
(: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
; so that for cljs it's loaded as macros expand to this
[com.rpl.specter.defnavhelpers])
#?(:clj (:import [com.rpl.specter.impl RichNavigator])))
@ -293,7 +296,7 @@
then-nav
else-nav)
idx (if test? params-idx (+ params-idx then-params))]
(i/exec-rich-select*
(i/exec-rich_select
sel
params
idx
@ -309,7 +312,7 @@
then-nav
else-nav)
idx (if test? params-idx (+ params-idx then-params))]
(i/exec-rich-transform*
(i/exec-rich_transform
tran
params
idx
@ -460,19 +463,11 @@
(walk/walk (partial walk-until pred on-match-fn) identity structure)))
(defn codewalk-until [pred on-match-fn structure]
(if (pred structure)
(on-match-fn structure)
(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))))
(def DISPENSE*
(i/no-params-rich-compiled-path
(reify i/RichNavigator
(rich-select* [this params params-idx vals structure next-fn]
(reify RichNavigator
(rich_select [this params params-idx vals structure next-fn]
(next-fn params params-idx [] structure))
(rich-transform* [this params params-idx vals structure next-fn]
(rich_transform [this params params-idx vals structure next-fn]
(next-fn params params-idx [] structure)))))

View file

@ -10,3 +10,12 @@
~backup-res
~aseq))
(defmacro definterface+ [name & methods]
(let [platform (if (contains? &env :locals) :cljs :clj)]
(if (= platform :cljs)
`(defprotocol ~name ~@methods)
(let [methods (for [[n p & body] methods]
(concat [n (-> p next vec)] body))]
`(definterface ~name ~@methods)))))