Check arg count manually in `and`/`or`; refine `bind-args`.
catseye
12 years ago
3 | 3 |
### `bind-args` ###
|
4 | 4 |
|
5 | 5 |
| (robin (0 1) ((small (0 1) *) (bind-args (0 1) *))
|
6 | |
| (bind-args (a b) (list 1 2)
|
|
6 |
| (bind-args (a b) (1 2)
|
7 | 7 |
| (list a b)))
|
8 | 8 |
= (1 2)
|
9 | 9 |
|
|
10 |
Expressions in the list of values are evaluated.
|
|
11 |
|
10 | 12 |
| (robin (0 1) ((small (0 1) *) (bind-args (0 1) *))
|
11 | |
| (bind-args (a b) (list 1)
|
|
13 |
| (bind-args (a b) ((subtract 5 4) (subtract 10 1))
|
|
14 |
| (list a b)))
|
|
15 |
= (1 9)
|
|
16 |
|
|
17 |
Too many or too few arguments will raise an `illegal-arguments`
|
|
18 |
exception.
|
|
19 |
|
|
20 |
| (robin (0 1) ((small (0 1) *) (bind-args (0 1) *))
|
|
21 |
| (bind-args (a b) (1)
|
12 | 22 |
| (list a b)))
|
13 | 23 |
? uncaught exception: (illegal-arguments (1))
|
14 | 24 |
|
15 | 25 |
| (robin (0 1) ((small (0 1) *) (bind-args (0 1) *))
|
16 | |
| (bind-args (a b) (list 1 2 3)
|
|
26 |
| (bind-args (a b) (1 2 3)
|
17 | 27 |
| (list a b)))
|
18 | 28 |
? uncaught exception: (illegal-arguments (1 2 3))
|
|
29 |
|
|
30 |
The literal arguments are reported in the exception.
|
|
31 |
|
|
32 |
| (robin (0 1) ((small (0 1) *) (bind-args (0 1) *))
|
|
33 |
| (bind-args (a) ((subtract 5 4) (subtract 1 0))
|
|
34 |
| a))
|
|
35 |
? uncaught exception: (illegal-arguments ((subtract 5 4) (subtract 1 0)))
|
3 | 3 |
(let (
|
4 | 4 |
(bind-args
|
5 | 5 |
(macro (self args env)
|
6 | |
;''(head args) is the literal list of identifiers;
|
7 | |
(eval env (head (tail args))) is the list of
|
8 | |
values to be bound to those identifiers.''
|
9 | 6 |
(let (
|
10 | |
(id-list (head args))
|
11 | |
(orig-val-list (eval env (head (tail args))))
|
12 | |
(expr (head (tail (tail args))))
|
13 | |
(bind-args-r (fun (self id-list val-list env-acc)
|
|
7 |
(id-list (head args))
|
|
8 |
(orig-val-list (head (tail args)))
|
|
9 |
(expr (head (tail (tail args))))
|
|
10 |
(bind-args-r (fun (self id-list val-list env-acc)
|
14 | 11 |
;''This will need to be converted into a macro at some point,
|
15 | 12 |
but for now, this is easier.''
|
16 | 13 |
(if (empty? id-list)
|
|
21 | 18 |
(raise (list (literal illegal-arguments) orig-val-list))
|
22 | 19 |
(self self (tail id-list) (tail val-list)
|
23 | 20 |
(prepend
|
24 | |
(list (head id-list) (head val-list))
|
|
21 |
(list (head id-list) (eval env (head val-list)))
|
25 | 22 |
env-acc))))))
|
26 | 23 |
(new-env (bind-args-r bind-args-r id-list orig-val-list env))
|
27 | 24 |
)
|
0 | |
(robin (0 1) ((small (0 1) *) (env (0 1) *))
|
|
0 |
(robin (0 1) ((small (0 1) *) (env (0 1) *) (list (0 1) *))
|
1 | 1 |
(let (
|
2 | 2 |
(and (macro (self args env)
|
3 | |
(if (eval env (head args))
|
4 | |
(if (eval env (head (tail args))) #t #f)
|
5 | |
#f)))
|
|
3 |
(if (equal? (length args) 2)
|
|
4 |
(if (eval env (head args))
|
|
5 |
(if (eval env (head (tail args))) #t #f)
|
|
6 |
#f)
|
|
7 |
(raise (list (literal illegal-arguments) args)))))
|
6 | 8 |
(and* (macro (self args env)
|
7 | 9 |
(if (equal? args ())
|
8 | 10 |
#t
|
|
16 | 18 |
(conj (fun (li)
|
17 | 19 |
(conj-r conj-r li)))
|
18 | 20 |
(or (macro (self args env)
|
19 | |
(if (eval env (head args))
|
20 | |
#t
|
21 | |
(if (eval env (head (tail args))) #t #f))))
|
|
21 |
(if (equal? (length args) 2)
|
|
22 |
(if (eval env (head args))
|
|
23 |
#t
|
|
24 |
(if (eval env (head (tail args))) #t #f))
|
|
25 |
(raise (list (literal illegal-arguments) args)))))
|
22 | 26 |
(or* (macro (self args env)
|
23 | 27 |
(if (equal? args ())
|
24 | 28 |
#f
|