Let's start Scheme

2014-01-16

よろしいならば戦争だ(マクロ編)

もう何度目の戦だか覚えてもいない。

CLOS周りで微妙なkludgeを使っているのが嫌になって、えいやっと書き換えてやれと思ったらバグを発見したという話。

再現コードとしては以下のようなの。
(import (rnrs))

(define-syntax aif
  (lambda (x)
    (syntax-case x ()
      ((aif expr then else)
       (with-syntax ((it (datum->syntax #'aif 'it)))
  #'(let ((it expr))
      (if it then else)))))))
(define-syntax wrap
  (syntax-rules ()
    ((_)
     (aif 'ok it #f))))


(wrap) ;; => error
(wrap)はokを返さないといけないんだけど、itがないって怒る。まぁ、原因も実は分かっていて、wrap内でitはテンプレート変数に変換されるんだけど、これに変換されるとコンパイラがうまいこと局所変数を参照できないという問題だったりする。

正直現在の実装は中身がぐちゃぐちゃになりすぎてて、何をやっているのかがコメントと記憶を頼りにするしかないのだが、このパターンは単純にもれている気がする。ただ、どうすればいいのかというのが今一分かっていない。例えば、上記の場合ならコンパイラが参照する環境に含まれる局所変数は識別子になっているので、識別子+テンプレート変数の組み合わせを参照する際に何かすればいいような気がするが、これが何かを壊すのではないかという不安もあって、う~んといった感じである。

まぁ、一つ分かっているのは、これは多分明日のリリースには間に合わないということかw

No comments:

Post a Comment