【问题标题】:Split a Prolog predicate into two parts and execute some code in between将 Prolog 谓词拆分为两部分并在其间执行一些代码
【发布时间】:2015-10-14 15:06:00
【问题描述】:

假设我有一个用户可以像这样编写 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).

【问题讨论】:

  • 在将子句添加到动态谓词时执行所需的转换怎么样?

标签: prolog


【解决方案1】:

一种可能的解决方案是使用目标扩展机制将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.
-----------------

顶层的示例用法。首先,加载使用hook 对象扩展它的Prolog 文件:

| ?- logtalk_load('user.pl', [hook(hook)]).
...

其次,简单地调用转换后的用户谓词:

| ?- pred(userPred, OutputList).
...

这对你有用吗?

【讨论】:

  • 现在我找到了一种让我工作的方法,但我也喜欢你的想法。 split_here 谓词的必要性是因为我没有考虑这种可能性。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多