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).
或者更确切地说:每个辅助参数的一个版本,因此
:- meta_predicate cont0_to(0,0).
:- meta_predicate cont1_to(1,1).
:- meta_predicate cont2_to(2,2).
...
名称可能更好,但操作员不会这样做。