在序言中转换元谓词

Transform in meta-predicate at prolog

我一直在阅读并注意到像 call 这样的谓词被称为元谓词,因此它们可以 return 其他谓词(不知道是否 return 在这里很好地使用了这个词)例如这里:

assert(call(goal, X,Y)).

编辑:潜伏者叫我推理,这行不通。

我知道它不应该调用谓词函数,但是有没有一种方法可以对直到运行时才知道的谓词进行断言?

我想对多个事实使用同一个插入谓词,所以 assert(fact(X)) 不适合我的需要。我可以在运行时检索事实的名称,但我如何在不直接统一事实的情况下使用断言?

您应该明确使用 assertz/1asserta/1assert/1assertz/1 的别名,但仅在某些 Prolog 系统中。

来电:

assertz(call(goal, X, Y)).

将尝试用函子 call 断言 事实 。这是它试图在数据库中断言的内容:

call(goal, _, _).

因为call 是一个已经在Prolog 中定义为谓词的仿函数,它会产生一个错误。例如,如果您要断言以下内容:

assertz(foo(goal, X, Y)).

它会成功,但是你在数据库中得到的是这样的:

foo(goal, _, _).

这似乎不是很有用。换句话说,断言只是按照您的要求进行:断言您刚刚描述的 term 在上述情况下其仿函数是 callfoo

如果你想断言一个实际的谓词,你只需要使用谓词是一个 term 的事实,其函子是 :-。一般谓词术语类似于 Head :- Body,或者以规范形式,':-'(Head, Body)。只要至少 Headassertz 调用之前实例化,就可以断言这种术语。

assertz(':-'(Head, Body)).

或等价地(因为 :- 是一个运算符):

assertz((Head :- Body)).

如果我这样做:

Head = goal, assertz((Head :- Body)).

我得到(使用listing/0):

:- listing.

goal :-
    call(_).

不是很有用。所以 Body 确实应该在调用 assertz/1 之前实例化。这是另一个例子:

Head = double(X, Y), Body = (Y is X * 2), assertz((Head :- Body)).

现在结果如下:

:- listing.

double(A, B) :-
        B is A * 2.