/
impl.cljs
82 lines (70 loc) · 2.03 KB
/
impl.cljs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
(ns applied-science.js-interop.impl
(:require-macros [applied-science.js-interop :as j]))
(def lookup-sentinel #js{})
(defn wrap-key
"Returns `k` or, if it is a keyword, its name."
[k]
(cond-> k
(keyword? k) (name)))
(defn ^boolean in?* [k* obj]
(js-in k* obj))
(defn ^boolean contains?* [obj k*]
(and (some? obj)
(in?* k* obj)))
(defn- get+! [o k*]
(if-some [child-obj (unchecked-get o k*)]
child-obj
(unchecked-set o k* #js{})))
(defn- get-value-by-keys
"Look up `ks` in `obj`, stopping at any nil"
[obj ks*]
(when obj
(let [end (count ks*)]
(loop [i 0
obj obj]
(if (or (= i end)
(nil? obj))
obj
(recur (inc i)
(unchecked-get obj (nth ks* i))))))))
(defn get-in*
([obj ks*]
(get-value-by-keys obj ks*))
([obj ks* not-found]
(if-some [last-obj (get-value-by-keys obj (butlast ks*))]
(let [k (peek ks*)]
(if (js-in k last-obj)
(j/unchecked-get last-obj k)
not-found))
not-found)))
(defn select-keys*
"Returns an object containing only those entries in `o` whose key is in `ks`"
[obj ks*]
(->> ks*
(reduce (fn [m k]
(cond-> m
^boolean (contains?* obj k)
(doto
(unchecked-set k
(unchecked-get obj k))))) #js {})))
(defn assoc-in*
[obj ks* v]
(let [obj (j/some-or obj #js{})
inner-obj (reduce get+! obj (butlast ks*))]
(unchecked-set inner-obj (peek ks*) v)
obj))
(defn update-in*
[obj ks* f args]
(let [obj (j/some-or obj #js{})
last-k* (peek ks*)
inner-obj (reduce get+! obj (butlast ks*))
old-val (unchecked-get inner-obj last-k*)]
(unchecked-set inner-obj
last-k*
(apply f old-val args))
obj))
(defn apply-in*
[obj ks* arg-array]
(let [parent (get-in* obj (pop ks*))
f (unchecked-get parent (peek ks*))]
(.apply f parent arg-array)))