(defn
tuple-impl
"Do not call this directly, use 'tuple'"
([forms preds] (tuple-impl forms preds nil))
([forms preds gfn]
(let
[specs (delay (mapv specize preds forms)) cnt (count preds)]
(reify
Specize
(specize* [s] s)
(specize* [s _] s)
Spec
(conform*
[_ x]
(let
[specs @specs]
(if-not
(c/and (vector? x) (= (count x) cnt))
:clojure.core/invalid
(loop
[ret x i 0]
(if
(= i cnt)
ret
(let
[v (x i) cv (conform* (specs i) v)]
(if
(invalid? cv)
:clojure.core/invalid
(recur
(if (identical? cv v) ret (assoc ret i cv))
(inc i)))))))))
(unform*
[_ x]
(assert (c/and (vector? x) (= (count x) (count preds))))
(loop
[ret x i 0]
(if
(= i (count x))
ret
(let
[cv (x i) v (unform (preds i) cv)]
(recur (if (identical? cv v) ret (assoc ret i v)) (inc i))))))
(explain*
[_ path via in x]
(cond
(not (vector? x))
[{:path path, :pred 'vector?, :val x, :via via, :in in}]
(not= (count x) (count preds))
[{:path path,
:pred
(clojure.core/sequence
(clojure.core/seq
(clojure.core/concat
(clojure.core/list 'clojure.core/=)
(clojure.core/list
(clojure.core/sequence
(clojure.core/seq
(clojure.core/concat
(clojure.core/list 'clojure.core/count)
(clojure.core/list '%)))))
(clojure.core/list (count preds))))),
:val x,
:via via,
:in in}]
:else
(apply
concat
(map
(fn
[i form pred]
(let
[v (x i)]
(when-not
(pvalid? pred v)
(explain-1 form pred (conj path i) via (conj in i) v))))
(range (count preds))
forms
preds))))
(gen*
[_ overrides path rmap]
(if
gfn
(gfn)
(let
[gen
(fn [i p f] (gensub p overrides (conj path i) rmap f))
gs
(map gen (range (count preds)) preds forms)]
(when (every? identity gs) (apply gen/tuple gs)))))
(with-gen* [_ gfn] (tuple-impl forms preds gfn))
(describe*
[_]
(clojure.core/sequence
(clojure.core/seq
(clojure.core/concat
(clojure.core/list 'clojure.core/tuple)
forms))))))))