taking off a parenthesis soo 21 Jun 2005 04:52 UTC
Let me introduce a funny idea. If the outer-most parenthesis of the let-formal is taken off, We can use the lambda-formal without additional key-words and parenthesis complexity. However, it is swindling by a clever trick, because the taken-off parenthesis should be inserted later. Of course, it becomes incompatible with r5rs-let*. Rough spec: (bare-let* (a1 a2 ...) ... () body1 body2 ...) (bare-let* ((a 10) (b 20)) ((c d e) (values 30 40 50)) ((f . g) (apply values '(60 70 80 90))) (h 100) () ; a parenthesis taken off (list a b c d e f g h)) => (10 20 30 40 50 60 (70 80 90) (100)) (define-syntax bare-let* (syntax-rules () ((bare-let* () clause ...) ((lambda () clause ...))) ((bare-let* ((name val) ...) clause ...) (let* ((name val) ...) (bare-let* clause ...))) ((bare-let* (formal vals) clause ...) (call-with-values (lambda () vals) (lambda formal (bare-let* clause ...)))))) It can be extended as followings. (bare-let* (_ (a 10) (b 20)) ; let (* (c 30) (d 40)) ; let* (% (e (lambda () 1))) ; letrec (& (f 50) (g 60)) ; and-let (&* (h 70) (i 80) (j 90)) ; and-let* (lp (k 100) (l 200)) ; named let (loop (m n . o) (apply values '(300 400))) ; named let (() (display (list k l m n o)) (newline)) ; begin (~ '(500 600) (p 1 (number? p)) (q 2)) ; let-optional (~* '(700 800 900) (r 3) (s 4) t) ;let-optional* () (display "examxple:") (if (< m 500) (loop 555 666 777 888) (list a b c d e f g h i j k l m n o p q r s t))) => (100 200 300 400 ()) examxple:(100 200 555 666 (777 888)) examxple:(10 20 30 40 #<procedure:e> 50 60 70 80 90 100 200 555 666 (777 888) 500 600 700 800 (900)) (define-syntax bare-let* (syntax-rules (~ ~* ! !* % & &* * _) ; @ # $ ^ + | ((bare-let* () clause ...) ((lambda () clause ...))) ((bare-let* ((name val) ...) clause ...) ((lambda (name ...) (bare-let* clause ...)) val ...)) ((bare-let* (_ (name val) ...) clause ...) (let ((name val) ...) (bare-let* clause ...))) ((bare-let* (* (name val) ...) clause ...) (let* ((name val) ...) (bare-let* clause ...))) ((bare-let* (% (name val) ...) clause ...) (letrec ((name val) ...) (bare-let* clause ...))) ((bare-let* (& (name val) ...) clause ...) (and-let ((name val) ...) (bare-let* clause ...))) ((bare-let* (&* (name val) ...) clause ...) (and-let* ((name val) ...) (bare-let* clause ...))) ;; The order of followings are important. ((bare-let* (~ rest p1 p2 ...) clause ...) (let-opt rest (p1 p2 ...) (bare-let* clause ...))) ((bare-let* (~* rest p1 p2 ...) clause ...) (let-opt* rest (p1 p2 ...) (bare-let* clause ...))) ((bare-let* (! rest p1 p2 ...) clause ...) (let-cat rest (p1 p2 ...) (bare-let* clause ...))) ((bare-let* (!* rest p1 p2 ...) clause ...) (let-cat* rest (p1 p2 ...) (bare-let* clause ...))) ((bare-let* (() expression ...) clause ...) ((lambda () expression ... (bare-let* clause ...)))) ((bare-let* (loop (name val) ...) clause ...) ((letrec ((loop (lambda (name ...) (bare-let* clause ...)))) loop) val ...)) ((bare-let* (loop formal vals) clause ...) (letrec ((loop (lambda formal (bare-let* clause ...)))) (call-with-values (lambda () vals) loop))) ((bare-let* (formal vals) clause ...) (call-with-values (lambda () vals) (lambda formal (bare-let* clause ...)))))) (define-syntax and-let (syntax-rules () ((and-let ((name val) ...) body1 body2 ...) (and val ... ((lambda (name ...) body1 body2 ...) val ...))) ;; ((and-let tag ((name val) ...) body1 body2 ...) ;; (and val ... ;; ((letrec ((tag (lambda (name ...) body1 body2 ...))) ;; tag) ;; val ...))) )) (define-syntax and-let* (syntax-rules () ((and-let* () body1 body2 ...) ((lambda () body1 body2 ...))) ((and-let* ((name1 val1) (name2 val2) ...) body1 body2 ...) ;;(and-let ((name1 val1)) ;; (and-let* ((name2 val2) ...) body1 body2 ...))))) (and val1 ((lambda (name1) (and-let* ((name2 val2) ...) body1 body2 ...)) val1))))) -- Joo ChurlSoo