-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathchoose.robin
64 lines (45 loc) · 1.64 KB
/
choose.robin
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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
;'<<SPEC'
-> Tests for functionality "Evaluate Robin Expression (with Small)"
`choose` performs a series of tests and evaluates to the expression
associated with the test that passes.
| (choose (#t (literal hi)) (else (literal lo)))
= hi
| (choose (#f (literal hi)) (#t (literal med)) (else (literal lo)))
= med
| (choose (#f (literal hi)) (#f (literal med)) (else (literal lo)))
= lo
`choose` can have zero tests before the `else`.
| (choose (else (literal woo)))
= woo
`choose` does require an `else` branch, or else an abort value will be
produced.
| (choose (#f (literal hi)) (#f (literal med)))
? abort
| (choose)
? abort
Each branch of a `choose` needs to be a two-element list, or else an
abort value will be produced.
| (choose (#t) (else (literal lo)))
? abort
| (choose (#f 66) (else))
? abort
Bindings can be seen inside each of the branches, and inside the `else`.
| (bind n (literal hi) (choose (#t n) (else (literal lo))))
= hi
| (bind n (literal hi) (choose (#f (literal lo)) (else n)))
= hi
`choose` is basically equivalent to Scheme's `cond`.
'<<SPEC'
(define choose (fexpr (args env)
(bind choose-r (fexpr (iargs ienv)
(bind self (eval ienv (head iargs))
(bind items (eval ienv (head (tail iargs)))
(bind branch (head items)
(bind test (head branch)
(bind then (head (tail branch))
(if (equal? test (literal else))
(eval env then)
(if (eval env test)
(eval env then)
(self self (tail items))))))))))
(choose-r choose-r args))))