taking off parentheses of only a resting argument
soo 07 Jul 2005 07:07 UTC
The previous one seems to be deviated from the focus of this srfi.
Now I suggest taking off the parentheses of only a resting argument. Then the
following bare-let* becomes compatible with r5rs-let* and almost compatible
with let*-values, and any keyword such as values becomes needless.
Examples:
(bare-let* ((a 10)
(b c (values 20 30))
((d e . f) (values 1 2 3 4))
g 111 ; taking off a pair of parentheses
((h) 40) ; This can be omitted.
((i j) (values 50 60))) ; This can be omitted.
(list a b c d e f g h i j))
(srfi-let* ((a 10)
(b c (values 20 30))
((values d e . f) (values 1 2 3 4))
((values . g) 111)
((values h) 40)
((values i j) (values 50 60)))
(list a b c d e f g h i j))
(let*-values (((a) 10)
((b c) (values 20 30))
((d e . f) (values 1 2 3 4))
(g 111) ; incompatible with bare-let*
((h) 40)
((i j) (values 50 60)))
(list a b c d e f g h i j))
=> '(10 20 30 1 2 (3 4) (111) 40 50 60)
(define-syntax bare-let*
(syntax-rules ()
((bare-let* () body1 body2 ...)
((lambda () body1 body2 ...)))
;; extension --- intervening body
((bare-let* ((() a ...) clause ...) body1 body2 ...)
((lambda ()
a ...
(bare-let* (clause ...) body1 body2 ...))))
;; ;; If commenting out, it becomes incompatible with let*-values
;; ((bare-let* (((a b ...) c) clause ...) body1 body2 ...)
;; (error "bare-let*: syntax error" '((a b ...) c)))
((bare-let* (((a . b) c) clause ...) body1 body2 ...)
(call-with-values (lambda () c)
(lambda (a . b)
(bare-let* (clause ...) body1 body2 ...))))
((bare-let* ((a1 a2 a3 ...) clause ...) body1 body2 ...)
(many-let ((a1) (a2 a3 ...))
(bare-let* (clause ...) body1 body2 ...)))
;; extension --- I like direct escape.
((bare-let* ((a) clause ...) body1 body2 ...)
(call-with-current-continuation
(lambda (a)
(bare-let* (clause ...) body1 body2 ...))))
;; extension --- extended named-let*
((bare-let* ((a . b) clause ...) body1 body2 ...)
(dot-let ((a) b)
(bare-let* (clause ...) body1 body2 ...)))
;; ((bare-let* ((a . b) clause ...) body1 body2 ...)
;; (error "bare-let*: syntax error" '(a . b)))
((bare-let* (a b clause ...) body1 body2 ...)
(call-with-values (lambda () b)
(lambda a
(bare-let* (clause ...) body1 body2 ...))))))
(define-syntax many-let
(syntax-rules ()
((many-let ((a ...) (a1 a2 a3 ...)) body1 body2 ...)
(many-let ((a ... a1) (a2 a3 ...)) body1 body2 ...))
((many-let ((a a1 ...) (b)) body1 body2 ...)
(call-with-values (lambda () b)
(lambda (a a1 ...) body1 body2 ...)))))
(define-syntax dot-let
(syntax-rules ()
((dot-let ((a ...) (an . bn)) body1 body2 ...)
(dot-let ((a ... an) bn) body1 body2 ...))
((dot-let ((a a1 ...) b) body1 body2 ...)
(%dot-let (() (a a1 ...) b) body1 body2 ...))))
(define-syntax %dot-let
(syntax-rules ()
((%dot-let (((n v) ...) ((n1 v1) a2 ...) b) body1 body2 ...)
(%dot-let (((n v) ... (n1 v1)) (a2 ...) b) body1 body2 ...))
((%dot-let (((n v) ...) (a1 a2 ...) b) body1 body2 ...)
(%dot-let (((n v) ... (a1 a1)) (a2 ...) b) body1 body2 ...))
((%dot-let (((n v) ...) () b) body1 body2 ...)
((letrec ((b (lambda (n ...) body1 body2 ...)))
b)
v ...))))
;; extended example
(bare-let* ((a 10)
(b c (values 20 30))
d 1000
(h)
((k 11) a (l 22) . m)
(() (display "test") (newline))
((e f . g) (apply values '(1 2 3 4 5))))
(if (< a 20)
(begin (display (list a b c k l)) (newline) (m 100 200 300))
(display (list a b c k l d e f g h)))
(newline)
(display "this is a test")
(newline)
(h)
(display "this is not seen")
(newline))
=>
test
(10 20 30 11 22)
test
(200 20 30 100 300 (1000) 1 2 (3 4 5) #<continuation>)
this is a test
--
Joo ChurlSoo