-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathsrfi-5-impl.scm
66 lines (53 loc) · 2.16 KB
/
srfi-5-impl.scm
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
65
66
;; Use your own standard let.
;; Or call a lambda.
;; (define-syntax standard-let
;;
;; (syntax-rules ()
;;
;; ((let ((var val) ...) body ...)
;; ((lambda (var ...) body ...) val ...))))
(define-syntax let
(syntax-rules ()
;; No bindings: use standard-let.
((let () body ...)
(standard-let () body ...))
;; Or call a lambda.
;; ((lambda () body ...))
;; All standard bindings: use standard-let.
((let ((var val) ...) body ...)
(standard-let ((var val) ...) body ...))
;; Or call a lambda.
;; ((lambda (var ...) body ...) val ...)
;; One standard binding: loop.
;; The all-standard-bindings clause didn't match,
;; so there must be a rest binding.
((let ((var val) . bindings) body ...)
(let-loop #f bindings (var) (val) (body ...)))
;; Signature-style name: loop.
((let (name binding ...) body ...)
(let-loop name (binding ...) () () (body ...)))
;; defun-style name: loop.
((let name bindings body ...)
(let-loop name bindings () () (body ...)))))
(define-syntax let-loop
(syntax-rules ()
;; Standard binding: destructure and loop.
((let-loop name ((var0 val0) binding ...) (var ... ) (val ... ) body)
(let-loop name ( binding ...) (var ... var0) (val ... val0) body))
;; Rest binding, no name: use standard-let, listing the rest values.
;; Because of let's first clause, there is no "no bindings, no name" clause.
((let-loop #f (rest-var rest-val ...) (var ...) (val ...) body)
(standard-let ((var val) ... (rest-var (list rest-val ...))) . body))
;; Or call a lambda with a rest parameter on all values.
;; ((lambda (var ... . rest-var) . body) val ... rest-val ...))
;; Or use one of several other reasonable alternatives.
;; No bindings, name: call a letrec'ed lambda.
((let-loop name () (var ...) (val ...) body)
((letrec ((name (lambda (var ...) . body)))
name)
val ...))
;; Rest binding, name: call a letrec'ed lambda.
((let-loop name (rest-var rest-val ...) (var ...) (val ...) body)
((letrec ((name (lambda (var ... . rest-var) . body)))
name)
val ... rest-val ...))))