Guile基礎/モジュールシステムの概要

変更履歴

概 要

目 次

参考資料

モジュールに関する一般的な説明

Guileのモジュールは,名前の付いた手続きや変数やマクロの集まりです. もっと正確に言うと,モジュール(module)は, シンボル(名前)のSchemeオブジェクトへの束縛の集合です.

モジュールの中では,すべての束縛はvisibleです. つまり,すべての束縛が利用できます. 幾つかの束縛は,エクスポートリスト(export list) に登録することによって, 他のモジュールやプログラムに公開できます. 公開された束縛の集合のことを, そのモジュールのパブリックインターフェース(public interface)と呼びます.

あるモジュールの公開された束縛は, そのモジュールが定めたパブリックインターフェースを通して利用することができます.さらに,モジュールを利用する際に, パブリックインターフェースを独自に調整することによって,カスタムインタフェースを定義することもできます. カスタムインターフェースでは,束縛の一部を選択したり, 束縛の名前を変更したりできます.

すべてのモジュールは, (ice-9 popen) とか (srfi srfi-11) などのような一意的な名前(モジュール名)を持ちます. モジュール名は1つ以上のシンボルのリストとして表現され,そのリストは, ファイルシステムにおけるモジュールファイルの相対パスを示しています. 相対パスの起点は,%load-path%load-compiled-path に登録されたディレクトリです.

あるモジュールが他のプログラムから利用されるとき,Guileは, まずそのモジュールがすでにロードされているかどうかを検査します. そのモジュールがまだロードされていないとき,Guileはそのモジュール名からモジュールファイルを検索してロードします.

モジュールの所在

グローバル変数 %load-path

▹ Guileは,あらゆるモジュール(ソースコード)を,%load-path に登録されたディレクトリを検索してロードします. このグローバル変数の値はディレクトリのリストです. 例えば,筆者の環境では次のようなリストになっています.
$ guile
GNU Guile 3.0.5
      ...... 起動メッセージ ...... 
guile> %load-path
$1 = ("/usr/share/guile/3.0" "/usr/share/guile/site/3.0" "/usr/share/guile/site" "/usr/share/guile")
guile> 

%load-path の値は,
(list (%library-dir) (%site-dir) (%global-site-dir) (%package-data-dir))
という式によって初期設定されます.この式を試しに実行してみると, その結果は上記の %load-path の値と一致します. ちなみに,筆者の環境では,%load-path に登録されているディレクトリのうち, 先頭の /usr/share/guile/3.0 だけが存在し,他のディレクトリは存在しません. 他のディレクトリは,必要に応じて自前で作成するのだと思います.

▹ モジュール(ソースコード)を新たに作成して, どこかのディレクトリに格納したときには, そのディレクトリを %load-path に登録しなければなりません. その登録方法は,モジュールを定義する方法と一緒に説明します.

グローバル変数 %load-compiled-path

▹ Guileは,モジュールのソースコードをVMコードにコンパイルします. そのVMコードは, グローバル変数 %load-compiled-path に登録されたディレクトリにキャッシュされ,再利用されます.このグローバル変数の値はディレクトリのリストです. 例えば,筆者の環境では次のようなリストになっています.
$ guile
GNU Guile 3.0.5
      ...... 起動メッセージ ......
guile> %load-compiled-path
$1 = ("/usr/lib/x86_64-linux-gnu/guile/3.0/ccache" "/usr/lib/x86_64-linux-gnu/guile/3.0/site-ccache")
guile> 

%load-compiled-path の初期値は, の2つの要素からなります. 筆者の環境では,上記の第1要素がGuile用のディレクトリで, 第2要素がサイト固有のディレクトリです. ただし,筆者の環境ではサイト固有のディレクトリは存在していません. これも必要に応じて作成するのだと思います.

モジュールのロード

▹ Guileは,モジュールをおおよそ次の手順に沿ってロードします.
  1. モジュール名(下記参照)が示すモジュールのソースコードのファイルと,キャッシュされているVMコードのファイルを探します.
  2. キャッシュされているVMコードがソースコードより古くなければ, そのVMコードをロードします.
  3. VMコードがキャシュされていない(存在しない)か, または,ソースコードより古いときには, ソースコードをコンパイルして, コンパイル後のVMコードをキャッシュして, そのVMコードをロードします.
%load-path や %load-compiled-path には複数のディレクトリが登録されているので, ディレクトリに対する検索の順序があるはずです. 残念ながら,マニュアルを見ても順序に関する記述を見つけ出せないのですが, 常識的にはそれぞれのリストの先頭から検索するのだろうと思います.

モジュール名とモジュールファイル

モジュール名とは

▹ モジュール名は,
(ice-9 textual-ports) や (ice-9 regex) や (srfi srfi-11)
などのように,シンボルのリストです. ただし,各シンボルにクォート(')は付けません. これらのモジュール名は,モジュールファイルの相対パスを示しています. 相対パスの起点は %load-path や %load-compiled-path に登録されているディレクトリです. 例えば,
(ice-9 textual-ports)
というモジュール名は
ice-9/textual-ports.scm  (ソースコード)
ice-9/textual-ports.go  (VMコード)
というファイル(の相対パス)を示しています. ソースコードファイルの起点は %loda-path に登録されているディレクトリで, VMコードファイルの起点は %load-compiled-path に登録されているディレクトリです. ただし, ".scm" はソースコードファイルの標準の拡張子で, ".go" はVMコードファイルの標準の拡張子です. これらは自動的に付加されます.

モジュール名の一般的な形式

▹ 一般に,Guileのモジュール名は,次のような形式のリストです.
(subdir$_1$ ... subdir$_n$ filename)
ここで:

モジュールファイルの拡張子

▹ Guileは,モジュールのソースコードのファイルを検索するとき, モジュール名が表現する相対パスに, %load-extensions に登録された拡張子を付けて検索します. %load-extensions は,ソースコードファイルの拡張子のリストを値とするグローバル変数です. 例えば,筆者の環境では以下に示すようなリストです.
$ guile
GNU Guile 3.0.5
guile> %load-extensions
$1 = (".scm" "")
guile> 
このグローバル変数に新たな拡張子(例えば,".mod"など)を登録すれば, その拡張子でも検索を行うのだと思います.

ソースコードファイルの拡張子は設定可能になっていますが, VMコードファイルの拡張子は .go で固定されています.
(おしまい)