Merge pull request #532 from dubek/vhdl-fix-defmacro
[jackhill/mal.git] / impls / lib / test_cascade.mal
CommitLineData
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))))))