For Gauche 0.9.5


Next: , Previous: , Up: マクロ   [Contents][Index]

5.4 マクロの展開

Function: macroexpand form
Function: macroexpand-1 form

form がリストで、その最初の要素が大域的にマクロに束縛された 変数であるならば、macroexpand-1はそのマクロ変換子を実行し、 展開されたフォームを返します。そうでなければ、form をそのまま 返します。

macroexpand は、form が展開できなくなるまで macroexpand-1 を繰り返します。

これらの手続きは、大域的に定義されたマクロを展開するために使うことが できます。

Function: macroexpand-all form

form中にあるマクロを全て展開します。結果の中に残るのは、 関数呼び出しとGaucheの組み込み構文だけになります。 formは現在のモジュール中のトップレベルにあるものと解釈されます (現在のモジュールについてはモジュールのセマンティクスを参照してください。 この概念はちょっとややこしいです。コンパイル時と実行時で 現在のモジュールが異なる場合があるからです。)

form中で導入されるローカル変数は全て、衝突を避けるためにリネームされます。 ローカル変数が全て固有の名前を持つようになるので、letフォームはすべて letrecで表されます(letによる束縛が他の束縛をシャドウしないと わかっていれば、letletrecに置き換えても意味は変わりません)。

注意: もしform内で呼ばれているマクロが、他のモジュール中にあるグローバル 変数への参照を挿入した場合、現在の実装ではその情報は失われてしまいます。 いくつか、その問題を修正する方法は考えられるのですが(例えば他のモジュール中に グローバル変数参照は識別子オブジェクトのまま残しておくとか、 with-moduleフォームに変換するとか、 そういったケースのための特殊構文を導入するとか)、今のところどうするか 決まっていません。なので、現在のふるまいにあまり依存しないようにしてください。 今のところ、この手続きは、マクロの展開結果をインタラクティブに確かめる用途に 限って使うのが安全です。

(macroexpand-all
 '(letrec-syntax
      [(when-not (syntax-rules ()
                   [(_ test . body) (if test #f (begin . body))]))]
    (let ([if list])
      (define x (expt foo))
      (let1 x 3
        (when-not (bar) (if x))))))
 ⇒ (letrec ((if.0 list)) 
     (letrec ((x.1 (expt foo)))
       (letrec ((x.2 '3)) 
        (if (bar) '#f (if.0 x.2)))))
Special Form: %macroexpand form
Special Form: %macroexpand-1 form

Next: , Previous: , Up: マクロ   [Contents][Index]