core: move condp macro to overlay
Phase 3 batch 5 (jolt-1j0). condp with a recursive emit building the nested if chain, including the test :>> result-fn form and the trailing default. This exhausts the cleanly-portable safe macros. conformance 228/228 x3, full suite green.
This commit is contained in:
parent
24b217d314
commit
394bbe07c3
3 changed files with 25 additions and 22 deletions
|
|
@ -106,3 +106,22 @@
|
|||
(let [binds (reduce (fn [acc spec] (conj (conj acc (first spec)) `(fn* ~@(rest spec))))
|
||||
[] fnspecs)]
|
||||
`(let* [~@binds] ~@body)))
|
||||
|
||||
;; condp: clauses are test-expr result-expr, or test-expr :>> result-fn (calls
|
||||
;; result-fn on the truthy (pred test-expr value)); a lone trailing expr is the
|
||||
;; default. The recursive emit builds a nested if chain.
|
||||
(defmacro condp [pred expr & clauses]
|
||||
(let [gp (fresh-sym) ge (fresh-sym)
|
||||
emit (fn emit [args]
|
||||
(let [n (if (= :>> (second args)) 3 2)
|
||||
clause (take n args)
|
||||
more (drop n args)
|
||||
cn (count clause)]
|
||||
(cond
|
||||
(= 0 cn) `(throw (ex-info (str "No matching clause: " ~ge) {}))
|
||||
(= 1 cn) (first clause)
|
||||
(= 2 cn) `(if (~gp ~(first clause) ~ge) ~(second clause) ~(emit more))
|
||||
:else `(if-let [p# (~gp ~(first clause) ~ge)]
|
||||
(~(nth clause 2) p#)
|
||||
~(emit more)))))]
|
||||
`(let [~gp ~pred ~ge ~expr] ~(emit clauses))))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue