syntax-case 初挑戦

schemeのsyntax-caseマクロで遊んだりしている。まず、何を題材にしようかと考え、letに多少の構文を付け加えたものを以前にsyntax-rulesを使って定義してみたのを思い出した。
id:SaitoAtsushi:20070126:1169813763
要はdefineと同じような関数定義用の構文糖衣を付け加えたletである。
補助マクロがグローバルなのが嫌なカンジだったのでsyntax-caseを使えばなんとかできるかと考えて書いたのがこれ。

(define-syntax letf
  (lambda(y)
    (define decexpand
      (lambda (x)
        (syntax-case x ()
          ((dec ...)
          (let f ((dec #'(dec ...)))
            (syntax-case dec ()
              (() #'())
              ((a1 a2 ...)
               (with-syntax (((rest ...) (f #'(a2 ...))))
                 (syntax-case #'a1 ()
                   (((var arg ...) fbody)
                    #'((var (lambda(arg ...) fbody)) rest ...))
                   ((var obj)
                    #'((var obj) rest ...)))))))))))
    (syntax-case y ()
      ((_  (decs ...) body ...)
       (with-syntax ((expanded (decexpand #'(decs ...))))
         #'(let expanded body ...)))
      ((_  name (decs ...) body ...)
       (with-syntax ((expanded (decexpand #'(decs ...))))
         #'(let name expanded body ...))))))

どこまでがコンパイル時に動いてどこからが実行時のコードなのかよく意識しないとすぐに混乱する。結構難しいよコレ。
Document ID: 02c7056eb5c56eead355cafab89e007d