Shiro Kawai
shiro****@lava*****
2005年 5月 15日 (日) 10:34:36 JST
hygienicマクロは、動機は単純なんですが、厳密に定義しよう とすると底無し沼って感じですね。 Gaucheの実装もエッジケースで怪しいところが結構あります。 で、問題の一致条件ですが、これはhygienicマクロの前提である、 「マクロ展開で使う識別子は、マクロ定義時のものである (従って、 マクロ使用時の環境と干渉しない)」という命題の特殊な場合と 考えられます。 マクロ定義時の環境とマクロ使用時の環境が異なっていたら、 識別子の意味も異なるということです。 ;; 例1 (let-syntax ((m (syntax-rules (XX) ((m XX) 'x) ((m v) v)))) (m XX)) ==> x この場合、 マクロmの定義時のXXの束縛: 無し(グローバル) マクロmの使用時のXXの束縛: 無し(グローバル) なので、XXの意味は同じです。 ;; 例2 (let ((XX 3)) ;; [1] (let-syntax ((m (syntax-rules (XX) ((m XX) 'x) ((m v) v)))) (m XX))) ==> x この場合、 マクロmの定義時のXXの束縛: [1]で束縛されている マクロmの使用時のXXの束縛: [1]で束縛されている なので、やはりXXの意味は同じです。 ;; 例3 (let ((XX 3)) ; [1] (let-syntax ((m (syntax-rules (XX) ((m XX) 'x) ((m v) v)))) (let ((XX 5)) ; [2] (m XX)))) ==> 5 この場合、 マクロmの定義時のXXの束縛: [1]で束縛されている マクロmの使用時のXXの束縛: [2]で束縛されている なので、マクロシステムは「ふたつのXXは表記は同じだけど、 意味が違う。だから別の識別子として扱おう。」と考えます。 別の識別子なんで、mの定義でXXに与えられた特別な意味(リテラル 識別子)はmの使用時のXXには及ばないのです。 ;; 例4 (let-syntax ((m (syntax-rules (XX) ((m XX) 'x) ((m v) v)))) (let ((XX 5)) ; [1] (m XX))) ==> 5 この場合、 マクロmの定義時のXXの束縛: 無し (グローバル) マクロmの使用時のXXの束縛: [1]で束縛されている なので、やはりふたつのXXは別のものとして扱われます。 --shiro