WIP, transient navigators
This commit is contained in:
parent
64afc6835a
commit
b3e581f737
2 changed files with 128 additions and 0 deletions
|
|
@ -757,6 +757,55 @@
|
|||
(next-fn structure)
|
||||
))
|
||||
|
||||
(deftype TransientEndNavigator [])
|
||||
|
||||
(extend-protocol p/Navigator
|
||||
TransientEndNavigator
|
||||
(select* [this structure next-fn]
|
||||
[])
|
||||
(transform* [this structure next-fn]
|
||||
(let [res (next-fn [])]
|
||||
(reduce conj! structure res))))
|
||||
|
||||
(deftype TransientLastNavigator [])
|
||||
|
||||
(extend-protocol p/Navigator
|
||||
TransientLastNavigator
|
||||
(select* [this structure next-fn]
|
||||
(next-fn (nth structure (dec (count structure)))))
|
||||
(transform* [this structure next-fn]
|
||||
(let [i (dec (count structure))]
|
||||
(assoc! structure i (next-fn (nth structure i))))))
|
||||
|
||||
#+clj
|
||||
(defn transient-all-select
|
||||
[structure next-fn]
|
||||
(into [] (r/mapcat #(next-fn (nth structure %))
|
||||
(range (count structure)))))
|
||||
|
||||
#+cljs
|
||||
(defn transient-all-select
|
||||
[structure next-fn]
|
||||
(into []
|
||||
(r/mapcat #(next-fn (nth structure %)))
|
||||
(range (count structure))))
|
||||
|
||||
(defn transient-all-transform!
|
||||
[structure next-fn]
|
||||
(reduce (fn [structure i]
|
||||
(assoc! structure i (next-fn (nth structure i))))
|
||||
structure
|
||||
(range (count structure))))
|
||||
|
||||
(deftype TransientAllNavigator [])
|
||||
|
||||
(extend-protocol p/Navigator
|
||||
TransientAllNavigator
|
||||
(select* [this structure next-fn]
|
||||
(transient-all-select structure next-fn))
|
||||
(transform* [this structure next-fn]
|
||||
(transient-all-transform! structure next-fn)))
|
||||
|
||||
(defn extract-basic-filter-fn [path]
|
||||
(cond (fn? path)
|
||||
path
|
||||
|
|
|
|||
79
src/clj/com/rpl/specter/transient.cljx
Normal file
79
src/clj/com/rpl/specter/transient.cljx
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
(ns com.rpl.specter.transient
|
||||
#+cljs
|
||||
(:require-macros [com.rpl.specter.macros
|
||||
:refer
|
||||
[defnav
|
||||
defpathedfn]])
|
||||
(:use #+clj
|
||||
[com.rpl.specter.macros :only
|
||||
[defnav
|
||||
defpathedfn]])
|
||||
(:require [com.rpl.specter.impl :as i]
|
||||
[com.rpl.specter :refer [subselect]]))
|
||||
|
||||
(defnav
|
||||
^{:doc "Navigates to the specified key of a transient collection,
|
||||
navigating to nil if it doesn't exist."}
|
||||
keypath!
|
||||
[key]
|
||||
(select* [this structure next-fn]
|
||||
(next-fn (get structure key)))
|
||||
(transform* [this structure next-fn]
|
||||
(assoc! structure key (next-fn (get structure key)))))
|
||||
|
||||
(def END!
|
||||
"Navigates to an empty (persistent) vector at the end of a transient vector."
|
||||
(i/comp-paths* [(i/->TransientEndNavigator)]))
|
||||
|
||||
(def FIRST!
|
||||
"Navigates to the first element of a transient vector."
|
||||
(keypath! 0))
|
||||
|
||||
(def LAST!
|
||||
"Navigates to the last element of a transient vector."
|
||||
(i/comp-paths* [(i/->TransientLastNavigator)]))
|
||||
|
||||
(def ALL!
|
||||
;; TODO: only works on transient vectors, not sets / maps; need a
|
||||
;; different name?
|
||||
"Navigates to each element of a transient vector."
|
||||
(i/comp-paths* [(i/->TransientAllNavigator)]))
|
||||
|
||||
(defpathedfn filterer!
|
||||
"Navigates to a view of the current transient vector that only
|
||||
contains elements that match the given path."
|
||||
[& path]
|
||||
(subselect ALL! (selected? path)))
|
||||
|
||||
(defn- select-keys-from-transient-map
|
||||
"Selects keys from transient map, because built-in select-keys uses
|
||||
`find` which is unsupported."
|
||||
[m m-keys]
|
||||
(loop [result {}
|
||||
m-keys m-keys]
|
||||
(if-not (seq m-keys)
|
||||
result
|
||||
(let [k (first m-keys)
|
||||
;; support Clojure 1.6 where contains? is broken on transients
|
||||
item (get m k ::not-found)]
|
||||
(recur (if-not (identical? item ::not-found)
|
||||
(assoc result k item)
|
||||
result)
|
||||
(rest m-keys))))))
|
||||
|
||||
(defnav
|
||||
^{:doc "Navigates to the specified persistent submap of a transient map."}
|
||||
submap!
|
||||
[m-keys]
|
||||
(select* [this structure next-fn]
|
||||
(select-keys-from-transient-map structure m-keys))
|
||||
(transform* [this structure next-fn]
|
||||
(let [selected (select-keys-from-transient-map structure m-keys)
|
||||
res (next-fn selected)]
|
||||
(as-> structure %
|
||||
(reduce (fn [m k]
|
||||
(dissoc! m k))
|
||||
% m-keys)
|
||||
(reduce (fn [m [k v]]
|
||||
(assoc! m k v))
|
||||
% res)))))
|
||||
Loading…
Reference in a new issue