たまにdefine-macroすると間違える

er-macroが早ければ次もしくは次の次のバージョンに入るのでそれを待ってください。

なんと。。(そんなに直ぐ入るとは思っていなかったので)
前回( http://d.hatena.ne.jp/mjt/20140914/p1 )のdefine-inject-syntaxのようなマクロはdefine-macroとsyntax-rulesが有れば実装できると思ってたけど、冷静に考えるとstraightforwardな方法は無さそう。letrecのような必要な構文要素の挿入のためにはsyntax-rulesで書いたマクロを呼べば良いと思ってたけど、それだと結局2つのマクロをエクスポートして呼び分けるしか無くなってしまう。
あと、Gaucheのdefine-macroでハマったのは:

(define (w f)
  (define h (macroexpand-1 f))
  (print h)
  (unless (equal? f h)
    (display "\n===========\n\n")
    (w h)))

(define-macro (ItIs10/body body)
  `(let ((it 10)) ,body))
(define-macro (ItIs10 body)
  (list ItIs10/body body))

(print "Expand ItIs10/body:")
(w '(ItIs10/body (print it)))
(print "Expand ItIs10:")
(w '(ItIs10 (print it)))

(newline)
(print "ItIs10Alt:")
(ItIs10/body (print it))
(print "ItIs10:")
(ItIs10 (print it))

ItIs10/bodyはitに10をbindするマクロで、ItIs10はItIs10/bodyを呼び出すマクロになっている。Expand結果の見た目は同じだが、ItIs10は期待通りに動作しない。

Expand ItIs10/body:
(let ((it 10)) (print it))

===========

(let ((it 10)) (print it))
Expand ItIs10:
(#<macro ItIs10/body> (print it))

===========

(let ((it 10)) (print it))

===========

(let ((it 10)) (print it))

ItIs10Alt:
10
ItIs10:
*** ERROR: unbound variable: it
Stack Trace:
_______________________________________
  0  it

  1  (print it)
        At line 78 of "./g.scm"

これは、

(define-macro (ItIs10 body)
  (list 'ItIs10/body body))

のようにItIs10/bodyにquoteをつけるとちゃんと動く。。scmではちゃんと動いたのに... と思ってたら、写したときにquoteを落していた。
マクロのデバッグはなかなか難しい。前回の define-inject-syntax も、マクロのトレースが最初から有るRacketとnmoshで全パタン(syntax-case、er-macro-transformer、lisp-transformer)を実装して、それからchibi-scheme等の他の処理系で動作確認している。nmoshは他のSchemeフロントエンドと比較してシンプルなのでデバッグしやすいが、今回のような問題を見逃してしまう(元がsyntax-caseなのでtransformerをquoteしない場合は値として扱えてしまう)。
不健全マクロは一年に1、2回も書かないので全然上手くならない気がする。syntax-rulesは日常的に書くけど。。そして偶にsyntax-caseを使うと、他と比べて表現力が高くて感心する。