ボンジュール・マドモアゼル

本サイトの情報は自己責任にてご利用下さい。

[Prolog] SWI-Prolog − モジュール

 
SWI-Prolog のモジュール機能について

SWI-Prolog におけるモジュールの構成を下図に示す。
SWI-Prolog モジュール構成
SWI-Prolog は、system と user のふたつの予約済みモジュールがある。
module/2 ディレクティブの指定がないファイルを consult した場合、user モジュールに述語が定義される。

以下、SWI-Prolog 5.10.2 Reference Manual の翻訳
誤訳があるかもしれない。色付き文字は訳者の補足。

5.10 Reserved Modules and using the `user' module
5.10 予約済みモジュールと user モジュールの使用

SWI-Prolog には2つの特別なモジュールが用意されている。ひとつめは、system モジュールである。このモジュールには、すべての組込み述語が含まれる。system モジュールは、インポートモジュールを持たない。ふたつ目の特別なモジュールは、user モジュールである。このモジュールは、ユーザの最初の作業空間を形成する。初期の作業空間には何もない。 userモジュールは、system モジュールをインポートしており、すべての組込み述語を利用できるようにしている。

他のすべてのモジュールは、user モジュールからインポートを行う。これは、それらのモジュールが、明示的にそれらをインポートせずとも user モジュールに対してインポートされたすべての述語が使えることを意味している。もしアプリケーションが、use_module/1を使ってuserモジュールからすべてのモジュールをロードする場合、特別な注意なしで、すべてのモジュールが、すべてのエクスポートされた述語にアクセスできる C言語と同様なスコープシステムを実現する。



5.2 Defining a Module
5.2 モジュールの定義

モジュールは、通常、モジュールファイルをロードすることで作成される。モジュールファイルは、 module/2 ディレクティブが最初の項として指定されているファイルのことである。 module/2 ディレクティブは、モジュールの名前と外部に公開する述語を宣言する。ファイルの残りの内容は、そのモジュールにロードされる。
以下は、モジュールファイルの例である。述語 reverse/2 と隠されたヘルパー述語 rev/3 を定義している。モジュールはすべての組込み述語を使うことができ、デフォルトでは、システム述語を再定義できない。redefine_system_predicate ディレクティブを使用することでシステム述語を再定義することが可能となる。
:- module(reverse, [reverse/2]).

reverse(List1, List2) :-
        rev(List1, [], List2).

rev([], List, List).
rev([Head|List1], List2, List3) :-
        rev(List1, [Head|List2], List3).

このモジュールの名前は、reverse である。典型的に、モジュール名は、拡張子を除いたファイル名と同じ名前で定義される。しかし、この命名規則は強制されるものではない。モジュールはフラットな唯一の名前空間に配置される。そのため、モジュール名は、衝突を避けるよう注意して選ばなければならない。
我々が見えるように、モジュールシステムの典型的アプリケーションは、ソーステキストで明示的にモジュールの名前をめったに使用しない。
:- module(+Module, +PublicList)
このディレクティブは、ソースファイルの最初の項でしか使うことは出来ない。これは、ファイルがモジュールファイルであることを宣言し、モジュール名を Module とし、PublicList にリストされた述語をエクスポートする。
PublicList は述語指示子 predicate indicator (name/arityname//arity)か、または op(Precedence, Type, Name) を使った演算子の宣言のリストである。
エクスポートリストで定義された演算子は、このモジュールをインポートしたモジュールと同様に、モジュールのなかで利用できる。section 4.23 も参照せよ。
(Ciao Prolog と互換)、もし、Module が束縛されていなければ、ロードされているファイルの拡張子を省いた basename で単一化される。例えば foo.pl に :- module(_, [bar/0]). と宣言した場合、モジュール foo が作成される。

5.4 Defining a meta-predicate
5.4 メタ述語の定義

メタ述語は、動的に他の述語を呼び出したり、述語を修正したり、述語の属性について推論などを行う述語である。メタ述語は、操作対象となる述語を記述するために、複合項か述部指示子(predicate indicator)を使用する。例:assert(name(jan)) abolish(name/1).
モジュールを導入すると、name+arity の組み合わせだけでは述語を特定することができなくなる。
これは、<module>:<term> という形式でモジュール名を修飾することで解決される。例:assert(person:name(jan)) abolish(person:name/1).
もちろん、我々は、assert/1 をモジュール内から呼び出すときには、述語をそのモジュールにローカルに assert することを期待する。言い換えれば、手作業による :/2の指定を避けたいのである。
meta_predicate/1 ディレクティブは、いくつかの引数が、述語を探索するのに使われる項であり、<module>:<term> のようにモジュール名が修飾されていない場合、モジュール名を補う必要があることをコンパイラに告げる。
下の例では、モジュール内で maplist/3 を定義するのに、このディレクティブを使っている。meta_predicate 宣言の引数 '2' は、この引数が、モジュール・センシティブであり、述語を呼び出すのに maplist/3 に渡されたもうふたつの項が使われるということを意味している。

コンパイラは、0..9 と : のみをモジュール・センシティブとして認識する。+ から ? までは、モードを示す。0..9 の値は、クロスリファレンスとシンタックス・ハイライティングで使用される。
ヘルパー述語 maplist_/3 には、meta-predicate 宣言が不要であることに注意せよ。なぜなら、maplist/3 が <module>:Goal としてモジュール名を修飾したものを、maplist_/3 に渡すからである。meta_predicate/1 の詳細を見よ。
:- module(maplist, [maplist/3]).
:- meta_predicate maplist(2, ?, ?).

%%      maplist(:Goal, +List1, ?List2)
%
%       True if Goal can successfully be applied to all
%       successive pairs of elements from List1 and List2.

maplist(Goal, L1, L2) :-
        maplist_(L1, L2, G).

maplist_([], [], _).
maplist_([H0|T0], [H|T], Goal) :-
        call(Goal, H0, H),
        maplist_(T0, T, Goal).
meta_predicate +Head, ...
カンマ区切りのリスト Head によって参照される述語をメタ述語として定義する。各頭部の各引数は、メタ引数指定子とする。指定子は以下のとおりに定義される。0..9 と : のみが解釈され、モード宣言 +, -, ? は無視される。

0..9
引数は、この引数の後に続くN 個の引数に与えられた項と一体で述語の参照を使用する項である。例:call(0) , maplist(1, +).

:
引数は、モジュール・センシティブであるが、直接的に述語を呼び出さない。例:consult(:).

-
引数は、モジュール・センシティブではない。かつ、入力において束縛されていない。

?
引数は、モジュール・センシティブではない。かつ、モード指定はない。

+
引数は、モジュール・センシティブではない。かつ、入力において束縛されている(nonvar など)。

モジュール・センシティブな各引数(0..9 か : でマークされたもの)は、モジュール名が修飾されていなければ、呼び出し側のコンテキストのモジュール名が修飾される。<atom> がモジュール名と(:/2ではない)項を示しているアトムであるところでは、実装は、引数が <module>:<term> で渡されることを保証する。
以下は、簡単な宣言といくつかの質問である。
:- meta_predicate
        meta(0, +).

meta(Module:Term, _Arg) :-
        format('Module=~w, Term = ~q~n', [Module, Term]).
?- meta(test, x).
Module=user, Term = test
?- meta(m1:test, x).
Module=m1, Term = test
?- m2:meta(test, x).
Module=m2, Term = test
?- m1:meta(m2:test, x).
Module=m2, Term = test
?- meta(m1:m2:test, x).
Module=m2, Term = test
?- meta(m1:42:test, x).
Module=42, Term = test

meta_predicate/1 宣言は、メタ述語を定義するための移植可能な機構であり、旧いSWI-Prologで提供された廃止予定の述語 module_transparent/1, context_module/1, strip_module/3 に取って代わられるものである。
<<SWI-Prolog − 4.1 Notation of Predicate Descriptions | ホーム | SWI-Prolog − 属性付き変数 (Attributed variables)>>

コメント

コメントの投稿

管理者にだけ表示を許可する

画像の文字を半角数字で下記ボックスに記入ください。
文字が読みにくい場合はブラウザの更新をすると新しい文字列が表示されます。