SWI メタ述語の宣言とモジュールは、Quintus、SICStus、および YAP のものと似ています。これらのシステムの基本的な前提は、すべての情報が を使用して宣言されたメタ引数を介して渡されること(:)/2です。隠された状態やコンテキストはありません。一般的なケース (単純なインスタンス化された引数) の場合、メタ述語宣言は、プログラマーからの明示的な修飾の負担を軽減するのに十分です。
ただし、現在のようなより複雑な状況では、明示的な修飾が追加されることを確認する必要があります。(:)/2さらに、それに応じてプレフィックスを「逆参照」する必要があります。SWIには、次のものがありますstrip_module/3。
?- strip_module(a:b:c:X,M,G).
X = G,
M = c.
次の定義を仮定します。
rec(_, -1, local).
rec(_, 0, =).
rec(F, 1, F).
local(S0,S) :-
S is S0+1.
これは次のように書く必要があります:
:- meta_predicate goal_qualified(:,-).
goal_qualified(G,G).
:- meta_predicate rec(2,+,2).
rec(_, -1, G) :-
strip_module(G,_,VG),
goal_qualified(local,VG).
rec(_, 0, G) :-
strip_module(G,_,VG),
goal_qualified(=,VG).
rec(F, 1, G) :-
strip_module(G,_,F).
多くの場合、モジュール プレフィックスを手動で追加することを好みます。
:- meta_predicate rec(2,+,2).
rec(_, -1, G) :-
strip_module(G,_,mymodule:local).
...
また、SWI のみに制限すると、SICStus または YAP との互換性が犠牲になります。
:- meta_predicate rec(2,+,2).
rec(_, -1, _:mymodule:local).
rec(_, 0, _:(=)).
rec(F, 1, _:F).
あなたの質問のルール
rec(F,N,\A^B^(call(F,A,H),call(G,H,B))) :-
N>1, M is N-1, rec(F,M,G).
したがって、次のように翻訳されます。
rec(F, N, MG) :-
N > 1, M is N - 1,
strip_module(MG,_,VG),
goal_qualified(\A^B^(call(F,A,H),call(G,H,B)),VG),
rec(F, M, G).
がどこにでもインポートされると仮定すると、library(lambda)これは SWI で次のように単純化できます。
rec(F, N, _:(\A^B^(call(F,A,H),call(G,H,B)) )) :-
N > 1, M is N -1,
rec(F, M, G).
私の結論
1mo: システムは、次のような句が常に失敗する場合に警告を生成する必要があります。
| ?- [user].
% compiling user...
| :- meta_predicate p(0).
| p(1).
% compiled user in module user, 0 msec 2080 bytes
yes
| ?- p(X).
no
2do: おそらく、次の補助述語を使用するのが最善でしょう:
:- meta_predicate cont_to(:,:).
cont_to(MGoal, MVar) :-
strip_module(MVar, _, Var),
( nonvar(Var)
-> throw(error(uninstantiation_error(Var),_))
; true
),
( strip_module(MGoal,_,Goal),
var(Goal)
-> throw(error(instantiation_error,_))
; true
),
Var = MGoal.
使用法。
rec(_, -1, MV) :-
cont_to(local, MV).
むしろ、補助引数の数ごとに1つのバージョン、したがって
:- meta_predicate cont0_to(0,0).
:- meta_predicate cont1_to(1,1).
:- meta_predicate cont2_to(2,2).
...
名前はもっと良いかもしれませんが、オペレーターはそうしません。