問題となるのは以下のようなコード。
(import (rnrs))
(define-syntax renaming-test
(syntax-rules ()
((_ var val)
(begin
(define dummy val)
(define (var) dummy)))))
(define dummy #f)
(renaming-test a 'a)
(print (a))
(print dummy)
まぁ、見れば分かるとおり、最後のdummyは#fを返してほしいのだがaを返してくるというバグである。要するにリネームが上手いこといっていないのである。現状ではリネームは展開時にのみ行われているのだが、パターンのコンパイル時にどこにも束縛されていない識別子はリネームしてしまっていいのではないか?という気がしている。上記の例なら、パターン変数であるvarとval、束縛されている_、begin及びdefineはリネームするとまずいのだが、残り(dummy)はリネームしてもマクロ外にもれることはないわけなのだから(むしろ漏れるとまずい)。ちょっとそんな感じでやってみるかね。 あぁ、だめだ。それだと以下のようなパターンで困る。
(let ((dummy #f)
(hoge #t))
(define (print . args) (for-each display args) (newline))
(let-syntax
((renaming-test (lambda (x)
(syntax-case x ()
((_ var val)
#'(begin
(define dummy val)
(define (var) dummy)
(display hoge) (newline)))))))
(renaming-test a 'a))
(print (a))
(print dummy))
これだと、dummyはリネームされてほしいけど、hogeは変更されたくない。ただ、このパターンってマクロが構文を知ってないとどうしようもないような。違うかな?dummyとhogeが意味的に違うってのを構文の情報なしにどう知ればいいんだ?
No comments:
Post a Comment