[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

taking off parentheses of only a resting argument

This page is part of the web mail archives of SRFI 71 from before July 7th, 2015. The new archives for SRFI 71 contain all messages, not just those from before July 7th, 2015.



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