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