デフォルトでは、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
フォーム等を使って。(機能条件式参照))