将 Prolog 谓词拆分为两部分并在其间执行一些代码
Split a Prolog predicate into two parts and execute some code in between
假设我有一个用户可以像这样编写 Prolog 谓词 pred/2
:
pred('an atom chosen by the user', OutputList) :-
%Part 1
%Here he can write every Prolog predicate that he wants
%and before split_here he has to inizialize the OutputList
...
split_here, %this is a special fact that that says where to split
%Part 2
%Here he can write every Prolog predicate that he wants
...
然后,我有某种引擎试图执行用户定义的 pred/2
,但为了提高效率,它需要在声明 split_here
的位置之间执行一些代码(比方说谓词 engine_code/0
).
我该如何实现这个模式?
第 1 部分和第 2 部分中的变量可以共享,而 engine_code/0
只关心 OutputList
(它包含什么样的术语并不重要)。
你能想出一个简单的方法来完成这个吗?
现在,我正在使用 clause/2
这样的:
clause(pred(X, OutputList), Body),
split(Body, split_here, Part1Goals, Part2Goals),
call(Part1Goals),
engine_code,
call(Part2Goals),
...
似乎当我在 call(Part1Goals)
和 call(Part2Goals)
之间写 engine_code/0
或者只是按顺序写时,变量没有共享。
例如:
pred(userPred, OutputList) :-
findall(myTerm(X,Y,Z), myTerm(X,Y,Z), OutputList),
split_here,
member(myTerm(X,_,_), OutputList),
use_x(X).
一个可能的解决方案是使用目标扩展机制将 split_here
标记替换为对 engine_code/0
谓词的调用。当您加载用户代码时,转换将完成。某些 Prolog 系统中提供了术语和目标扩展机制。对于适用于大多数编译器系统的可移植解决方案,您可以使用 Logtalk 的机制实现。例如:
---- user.pl ----
pred(userPred, OutputList) :-
findall(myTerm(X,Y,Z), myTerm(X,Y,Z), OutputList),
split_here,
member(myTerm(X,_,_), OutputList),
use_x(X).
-----------------
目标扩展代码:
---- hook.lgt ----
:- object(hook, implements(expanding)).
goal_expansion(split_here, engine_code).
:- end_object.
-----------------
来自顶级的示例用法。首先,加载 Prolog 文件,用 hook
对象扩展它:
| ?- logtalk_load('user.pl', [hook(hook)]).
...
其次,只需调用转换后的用户谓词:
| ?- pred(userPred, OutputList).
...
这对你有用吗?
假设我有一个用户可以像这样编写 Prolog 谓词 pred/2
:
pred('an atom chosen by the user', OutputList) :-
%Part 1
%Here he can write every Prolog predicate that he wants
%and before split_here he has to inizialize the OutputList
...
split_here, %this is a special fact that that says where to split
%Part 2
%Here he can write every Prolog predicate that he wants
...
然后,我有某种引擎试图执行用户定义的 pred/2
,但为了提高效率,它需要在声明 split_here
的位置之间执行一些代码(比方说谓词 engine_code/0
).
我该如何实现这个模式?
第 1 部分和第 2 部分中的变量可以共享,而 engine_code/0
只关心 OutputList
(它包含什么样的术语并不重要)。
你能想出一个简单的方法来完成这个吗?
现在,我正在使用 clause/2
这样的:
clause(pred(X, OutputList), Body),
split(Body, split_here, Part1Goals, Part2Goals),
call(Part1Goals),
engine_code,
call(Part2Goals),
...
似乎当我在 call(Part1Goals)
和 call(Part2Goals)
之间写 engine_code/0
或者只是按顺序写时,变量没有共享。
例如:
pred(userPred, OutputList) :-
findall(myTerm(X,Y,Z), myTerm(X,Y,Z), OutputList),
split_here,
member(myTerm(X,_,_), OutputList),
use_x(X).
一个可能的解决方案是使用目标扩展机制将 split_here
标记替换为对 engine_code/0
谓词的调用。当您加载用户代码时,转换将完成。某些 Prolog 系统中提供了术语和目标扩展机制。对于适用于大多数编译器系统的可移植解决方案,您可以使用 Logtalk 的机制实现。例如:
---- user.pl ----
pred(userPred, OutputList) :-
findall(myTerm(X,Y,Z), myTerm(X,Y,Z), OutputList),
split_here,
member(myTerm(X,_,_), OutputList),
use_x(X).
-----------------
目标扩展代码:
---- hook.lgt ----
:- object(hook, implements(expanding)).
goal_expansion(split_here, engine_code).
:- end_object.
-----------------
来自顶级的示例用法。首先,加载 Prolog 文件,用 hook
对象扩展它:
| ?- logtalk_load('user.pl', [hook(hook)]).
...
其次,只需调用转换后的用户谓词:
| ?- pred(userPred, OutputList).
...
这对你有用吗?