-
Notifications
You must be signed in to change notification settings - Fork 2
/
xforms.cljc
93 lines (86 loc) · 2.24 KB
/
xforms.cljc
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
81
82
83
84
85
86
87
88
89
90
91
92
93
(ns postmortem.xforms
(:refer-clojure :exclude [take-last drop-last]))
(defn take-until [pred]
(fn [rf]
(let [pred' (complement pred)]
(fn
([] (rf))
([result] (rf result))
([result input]
(if (pred' input)
(rf result input)
(reduced (rf result input))))))))
(defn drop-until [pred]
(fn [rf]
(let [dv (volatile! true)]
(fn
([] (rf))
([result] (rf result))
([result input]
(if @dv
(do (when (pred input)
(vreset! dv false))
result)
(rf result input)))))))
(defn take-last
([] (take-last 1))
([^long n]
(fn [rf]
(let [idx (volatile! 0)
vals (object-array n)]
(fn
([] (rf))
([result]
(let [i (long @idx)
start (if (>= i n) i 0)
end (if (>= i n) n i)]
(transduce (map #(aget vals (rem (+ % start) n))) rf result (range end))))
([acc input]
(aset vals (rem @idx n) input)
(vswap! idx inc)
acc))))))
(defn drop-last
([] (drop-last 1))
([^long n]
(fn [rf]
(let [vals (volatile! (transient []))]
(fn
([] (rf))
([result]
(let [m (max (- (count @vals) n) 0)]
(transduce (map #(@vals %)) rf result (range m))))
([acc input]
(vswap! vals conj! input)
acc))))))
(defn dedupe-by [f]
(fn [rf]
(let [prev (volatile! ::none)]
(fn
([] (rf))
([result] (rf result))
([acc input]
(let [p @prev
v (f input)]
(if (= p v)
acc
(do (vreset! prev v)
(rf acc input)))))))))
(defn- abs* ^double [^double x]
#?(:clj (Math/abs x)
:cljs (js/Math.abs x)))
(defn debounce
([interval] (debounce identity interval))
([f ^double interval]
(fn [rf]
(let [prev (volatile! ::none)]
(fn
([] (rf))
([result] (rf result))
([acc input]
(let [p @prev
v (f input)]
(if (or (= p ::none)
(>= (abs* (- v p)) interval))
(do (vreset! prev v)
(rf acc input))
acc))))))))