letのマクロ

letのマクロがどう展開されるか実験する。

本節では、導出式型をプリミティブ式型(リテラル、変数、手続き呼び出し、lambda、if、set!)に置き換えるマクロ定義を示す。

http://www.swiss.ai.mit.edu/~jaffer/r5rsj_9.html#SEC81

Gaucheのletは組み込みのSpecial Formでマクロではないので、R5RSの定義で上書きする。

(define-syntax let
  (syntax-rules ()
    ((let ((name val) ...) body1 body2 ...)
     ((lambda (name ...) body1 body2 ...)
      val ...))
    ((let tag ((name val) ...) body1 body2 ...)
     ((letrec ((tag (lambda (name ...)
                      body1 body2 ...)))
        tag)
      val ...))))

上記の定義をしてから、まずは普通に展開

gosh> (macroexpand '(let ((x 1) (y 2)) (+ x y)))
((#<identifier user#lambda> (x y) (+ x y)) 1 2)
gosh> (macroexpand '(let name ((x 1) (y 2)) (+ x y)))
((#<identifier user#letrec> ((name (#<identifier user#lambda> (x y) (+ x y)))) name) 1 2)

#の部分をidentifier->symbolで変換するために以下を追加

(define (map* f l) (map (lambda (x) (if (pair? x) (map* f x) (f x))) l))
(define (if-id x) (if (identifier? x) (identifier->symbol x) x))

これを使ってもう一度やってみる。

gosh> (map* if-id (macroexpand '(let ((x 1) (y 2)) (+ x y))))
((lambda (x y) (+ x y)) 1 2)
gosh> (map* if-id (macroexpand '(let name ((x 1) (y 2)) (+ x y))))
((letrec ((name (lambda (x y) (+ x y)))) name) 1 2)