デフォルトでは、GaucheはSchemeのトップレベルフォームをひとつづつ読み、 直ちに中間コードへとコンパイルして仮想マシンで実行します。 Gaucheをインタラクティブに使っている限りは、インタプリタのように思えるでしょう。 (実験的なAOTコンパイラもあります。試してみたい方は HOWTO-precompile.txtを見てください。)
コンパイルと実行のフェーズが分かれていることによって、 Gaucheをインタプリタと考えていると少々驚くことがあるかもしれません。 いくつか念頭に置いておくべき点をあげておきます。
loadはGaucheでは一般の関数なので、実行時に評価されます。
ロードされるファイル中でマクロを定義している場合、そのマクロは
そのloadの呼び出しを含むトップレベルフォームが評価された後で
有効になります。例えば、foo.scmがマクロfooを定義しているとして、
次のような用法を考えてみてください。
;; in “foo.scm” (define-syntax foo (syntax-rules () ((_ arg) (quote arg)))) ;; in your program (begin (load "foo") (foo (1 2 3))) ⇒ error, bad procedure: ‘1’ (load "foo") (foo (1 2 3)) ⇒ '(1 2 3)
beginでloadとfooの呼び出しを囲んだ場合、
コンパイラはまずbegin全体をコンパイルします。その時点でマクロ
fooは定義されていませんから、これは評価時にエラーになります。
一方、後者ではloadが評価されてからfooがコンパイルされるので、
問題は起きません。
このような混乱を避けるために、別のプログラムファイルを読み込む必要がある時は
requireかuseを使うことを勧めます。これらは構文であり、
コンパイラに認識されます。
上記の裏返しですが、requireとuseはコンパイル時に
解釈されます。したがって、ifなどの条件文のボディにこれらのフォームを
置いておいても、指定されたファイルは条件にかかわらず読み込まれてしまいます。
どうしてももし条件によって読み込むかどうかを変えたい場合は、loadを使うか、
条件判断自体をマクロで行うようにしてください。
(例えば、cond-expandフォーム等を使って。(機能条件式参照))