自由変数の決定(その3)

前回までの投稿で、Scheme(Gauche)ではレキシカルスコープが使われていることが分かった(たぶん)。そもそも、自由変数がどう決定されるのかを調べ始めるきっかけは、Schemeのマクロ内の自由変数がどう扱われるかをみるためだったので、それについても書いておく。

Schemeでは、マクロの定義方法として、define-syntaxを用いる方法と、define-macroを用いる方法があるが、この二つでは、自由変数の扱いが異なっている。

例えば、

(define-syntax stx
  (syntax-rules ()
    ((_) (print var))))

(define-macro (mcr)
  `(print var))

(define var 2)
(stx)   ;=> 2
(mcr)  ;=> 2

(let ((var 4)) (stx))   ;=> 2
(let ((var 4)) (mcr))  ;=> 4

となり、define-syntaxを使った時は、自由変数がマクロ定義場所の環境に従って決定されているが(健全)、define-macroを使うと、マクロ使用場所の環境で自由変数が決定されている(不健全)。

僕的には、マクロがS式を生成する機能である以上、define-macroの方が自然だと思うけど、define-syntaxの方がバグが起きにくいとも思う。