-
Notifications
You must be signed in to change notification settings - Fork 0
/
core.clj
44 lines (43 loc) · 1.76 KB
/
core.clj
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
(ns cond-plus.core)
(defmacro cond+
"Each test-expr is evaluated one at a time. If the test-expr returns logical
true (or is :else), the form is evaluated as described below and no further
cond-clauses are evaluated. (cond+) returns nil."
[& body]
(letfn
[(cond-loop
[tests]
(when (seq tests)
(let [line (first tests)
others (next tests)]
(if-not (or (list? line)
(vector? line))
(throw (IllegalArgumentException. "clause is not in a vector"))
(let [test (first line)
value (next line)]
(if (or (= 'else test)
(= :else test))
(if (seq others)
(throw (IllegalArgumentException. ":else not last"))
(if (nil? value)
(throw (IllegalArgumentException. "missing expression in else clause"))
`(let [] ~@value)))
(if (or (= '=> (first value))
(= :> (first value)))
(if (= 2 (count value))
(let [exp (cond-loop others)
gen (gensym)]
`(let [~gen ~test]
(if ~gen
(~(second value) ~gen)
~exp)))
(throw (IllegalArgumentException. "bad => clause")))
(let [exp (cond-loop others)]
(if (nil? value)
(let [gen (gensym)]
`(let [~gen ~test]
(if ~gen ~gen ~exp)))
`(if ~test
(let [] ~@value)
~exp))))))))))]
(cond-loop body)))