(import (rnrs)) (define-syntax aif (lambda (x) (syntax-case x () ((_ test then) #'(aif test then #f)) ((k test then else) (with-syntax ((it (datum->syntax #'k 'it))) #'(let ((it test)) (if it then else))))))) (aif (assq 'a '((a . 0))) it) ;; -> error理由は、一つ目のパターンが展開された際に挿入される
aif
は与えられた式のものではないためdatum->syntax
で生成される識別子が期待されるテンプレート識別子から生成されないため。_
をaif
として、置き換えの際に元の識別子が挿入されるようにすればOKになる。何が問題かといえば、Sagittariusはこれをエラーにしない。さらにまずいことに僕自身がこの動作を期待してコードを書いている点である。
datum->syntax
を多用した記憶はあまりないのだが、CLOS周りとかはかなり処理系の中身べったりで書いているので問題が起きる。また記憶が正しかったら(binary data)
辺りもこれ系の動作を期待しているような気がする。上記のような記憶にあって目に見えてる系のものならまだ救いがあるのだが(それでも影響範囲広いけど)、下記のような間接的に期待しているものがあると困る。
(define-syntax aif1 (syntax-rules () ((_ test then) (aif1 test then #f)) ((_ test then else) (aif test then else)))) (aif1 (assq 'a '((a . 0))) it)見た目的には
aif1
はaif
の薄いラッパーで単に式をaif
に移しているだけなのだが、これはR6RS的には動かない(はず)。が、Sagittariusでは動いてしまう。これ系のコードはdefine-method
で山ほど書いてる気がする。ここらで一発マクロ周りの見直しをしないといけないな。この辺りを網羅したR6RS準拠なテストケースがほしいところである。PLTのやつはマクロ周りのテストが貧弱すぎて、全パスしてもスタート地点にすら立ってない感じががが・・・
No comments:
Post a Comment