-
Notifications
You must be signed in to change notification settings - Fork 1
/
reduce.cljc
91 lines (75 loc) · 2.4 KB
/
reduce.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
(ns prpr.test.reduce
(:require
[promesa.core :as pr]
[prpr.promise :as prpr]
[prpr.error :as err]))
(def max-depth 20)
(defn seq-of-fns?
[v]
(and
(sequential? v)
(every? fn? v)))
(defn reduce-pr-fns*
"sequentially reduce a seq of
promise-returning 0-args fns into
Promise<[results]>"
[fns]
#_{:clj-kondo/ignore [:loop-without-recur]}
(pr/loop [rs []
depth 0
fns fns]
;; (prn "reduce-pr-fns: loop" (count rs) depth (count fns))
(let [[f & remf] fns]
(if (nil? f)
rs
(prpr/catch-always
(let [r-p (f)]
;; (prn "reduce-pr-fns: result-p" depth (type r-p))
(pr/let [r r-p]
;; (prn "reduce-pr-fns: derefed result" depth (type r))
(cond
;; if a form returns a single fn (or a promise of a fn)
;; and we're not beyond the max-depth, then call it
(fn? r)
#_{:clj-kondo/ignore [:redundant-do]}
(do
;; (prn "single fn")
(if (< depth max-depth)
(pr/recur
rs
(inc depth)
;; remf is a list, so conj puts r at the front
(conj remf r))
(err/wrap-uncaught
(ex-info "testing : max depth exceeded"
{:max-depth max-depth}))))
;; if a form returns a seq of fns, then call them
;; in order
(seq-of-fns? r)
#_{:clj-kondo/ignore [:redundant-do]}
(do
;; (prn "seq-of-fns")
(if (< depth max-depth)
(pr/recur
rs
(inc depth)
(concat r remf))
(err/wrap-uncaught
(ex-info "testing : max depth exceeded"
{:max-depth max-depth}))))
:else
#_{:clj-kondo/ignore [:redundant-do]}
(do
;; (prn "normal result")
(pr/recur
(conj rs r)
0
remf)))))
(fn [e]
(err/wrap-uncaught e)))))))
(defn reduce-pr-fns
[nm fns]
;; (println "reduce-pr-fns*: " nm)
(pr/let [r (reduce-pr-fns* fns)]
;; (println "reduce-pr-fns*: " nm ": done")
(err/unwrap r)))