Commit | Line | Data |
---|---|---|
dcdb6c02 NB |
1 | ;; Iteration on evaluations interpreted as boolean values. |
2 | ||
13e679cd NB |
3 | (load-file "../lib/load-file-once.mal") |
4 | (load-file-once "../lib/trivial.mal") ; gensym | |
26ced15b NB |
5 | |
6 | ;; `(cond test1 result1 test2 result2 .. testn resultn)` | |
7 | ;; is rewritten (in the step files) as | |
8 | ;; `(if test1 result1 (if test2 result2 (.. (if testn resultn nil))))` | |
9 | ;; It is common that `testn` is `"else"`, `:else`, `true` or similar. | |
10 | ||
11 | ;; `(or x1 x2 .. xn x)` | |
12 | ;; is almost rewritten as | |
13 | ;; `(if x1 x1 (if x2 x2 (.. (if xn xn x))))` | |
14 | ;; except that each argument is evaluated at most once. | |
15 | ;; Without arguments, returns `nil`. | |
16 | (defmacro! or (fn* [& xs] | |
17 | (if (< (count xs) 2) | |
18 | (first xs) | |
19 | (let* [r (gensym)] | |
e748a37d | 20 | `(let* (~r ~(first xs)) (if ~r ~r (or ~@(rest xs)))))))) |
26ced15b | 21 | |
dcdb6c02 NB |
22 | ;; Conjonction of predicate values (pred x1) and .. and (pred xn) |
23 | ;; Evaluate `pred x` for each `x` in turn. Return `false` if a result | |
24 | ;; is `nil` or `false`, without evaluating the predicate for the | |
25 | ;; remaining elements. If all test pass, return `true`. | |
26 | (def! every? | |
27 | (fn* (pred xs) | |
28 | ;; pred : Element -> interpreted as a logical value | |
29 | ;; xs : sequence of Elements x1 x2 .. xn | |
30 | ;; return : boolean | |
bf6647fb NB |
31 | (cond (empty? xs) true |
32 | (pred (first xs)) (every? pred (rest xs)) | |
33 | true false))) | |
dcdb6c02 NB |
34 | |
35 | ;; Disjonction of predicate values (pred x1) or .. (pred xn) | |
36 | ;; Evaluate `(pred x)` for each `x` in turn. Return the first result | |
37 | ;; that is neither `nil` nor `false`, without evaluating the predicate | |
38 | ;; for the remaining elements. If all tests fail, return nil. | |
39 | (def! some | |
40 | (fn* (pred xs) | |
41 | ;; pred : Element -> interpreted as a logical value | |
42 | ;; xs : sequence of Elements x1 x2 .. xn | |
43 | ;; return : boolean | |
44 | (if (empty? xs) | |
45 | nil | |
bf6647fb NB |
46 | (or (pred (first xs)) |
47 | (some pred (rest xs)))))) | |
dcdb6c02 NB |
48 | |
49 | ;; Search for first evaluation returning `nil` or `false`. | |
50 | ;; Rewrite `x1 x2 .. xn x` as | |
51 | ;; (let* [r1 x1] | |
52 | ;; (if r1 test1 | |
53 | ;; (let* [r2 x2] | |
54 | ;; .. | |
55 | ;; (if rn | |
56 | ;; x | |
57 | ;; rn) ..) | |
58 | ;; r1)) | |
59 | ;; Without arguments, returns `true`. | |
60 | (defmacro! and | |
61 | (fn* (& xs) | |
62 | ;; Arguments and the result are interpreted as boolean values. | |
bf6647fb NB |
63 | (cond (empty? xs) true |
64 | (= 1 (count xs)) (first xs) | |
65 | true (let* (condvar (gensym)) | |
66 | `(let* (~condvar ~(first xs)) | |
67 | (if ~condvar (and ~@(rest xs)) ~condvar)))))) |