モジュールの宣言は、このモジュールが現在の名前空間のどこかにあることだけです。これは、requireによって、またはコードに文字通りモジュールを書き出すことの両方によって行うことができます。
モジュールは、訪問およびインスタンスは、もう少しトリッキー理解することで、最高のように記述することができる。
モジュールは、位相レベル1(マクロ/コンパイルタイムコード)を実行している訪問し、そして相を実行していませんレベル0(ランタイムコード)。
モジュールインスタンシエーションは位相レベル0のコードを実行していますが、位相レベル1のコードは実行していません。それがコンパイルされていない場合
さて、トリッキーなビットは、位相レベル0のコードを実行するために、あなたが持っている必要があり、以前より高いレベルのすべてを実行するには、コードを段階的。しかし、このモジュールがすでに訪問されて(コンパイルされている場合)、フェーズレベル1のコードは再び実行されません。
これは、以下のモジュールで見ることができるが、test.rkt
と呼ば:
#lang racket
(require (for-meta 2 racket/base))
(displayln "phase 0")
(begin-for-syntax
(displayln "phase 1")
(begin-for-syntax
(displayln "phase 2")))
このモジュールは、位相0で実行されるコード、フェーズ1およびフェーズ2(マクロ展開フェーズのマクロ展開)を有しています。これらの各フェーズでは、フェーズが実行されていることを示す行が出力されます。このモジュールを使用すると、モジュールがインスタンス化された時刻がわかります。私たちはDrRacketでこれを実行すると、出力のようなものになります
#lang racket
(dynamic-require "test.rkt" #f)
:
さて、test.rkt
をインスタンス化し、次のファイルを作成してみましょう今
phase 2
phase 1
phase 0
を、私たちはのでphase 0
を見ますモジュールがインスタンス化されています。しかしこの場合、phase 2
とphase 1
も表示されます。これは、モジュールの構文フェーズがphase 0
コードを実行するために必ずインスタンス化されたためです。あなたは再びそれを実行する場合は
、あなたが取得します(電源がオンになって、すでにコンパイルされたファイルのキャッシュを持っていると仮定した場合):この場合
phase 0
をphase 1
と高いコードがすでに持っているので、あなただけphase 0
を見ます拡張されました。同様の結果を得るためには、動的には0
が必要です。今
、代わりにdynamic-require
に0
または#f
に渡すので、私たちは私たちに次のファイルを与える、(void)
に渡された場合:
#lang racket
(dynamic-require "test.rkt" (void))
を次に出力はあなたがキャッシングをオンにコンパイルしていると仮定すると、再び(になります
phase 1
これは、実行時(フェーズ0)コードではなく、マクロレベル(フェーズ1)コードがここで実行されているためです。我々はtest.rkt
にわずかな変更を加えると、(キャッシュを無効にするために)再びそれを保存すると、我々はなりますが:
phase 2
phase 1
をラケットはphase 1
コードを実行できるようにするために、phase 2
コードを展開していたためです。コンパイルされたモジュールのキャッシュが更新されていることをあなたは再びそれを実行した場合さて、それは出力のみの意志:
最後に
phase 1
、そこではありません(私が間違っている場合私の知る限り、これを更新してください) dynamic-require
を直接使用してフェーズレベル1より高いコードが実行されることを保証する方法はありません。