meta_predicate 的数字参数在 SWI-Prolog 中是什么意思?

What do the numeric arguments for meta_predicate mean in SWI-Prolog?

我正在编写一个 Prolog 程序,我正在尝试将模块合并到程序设计中以封装复杂性以减少冗余功能。

我遇到困难的一个功能是元谓词的使用。我想在一个模块中定义一个元谓词,然后将其导入另一个模块;这会带来并发症。幸运的是,meta_predicate 指令有助于解析模块前缀,但我无法理解这里描述的参数:https://www.swi-prolog.org/pldoc/man?section=metapred

具体来说,我在处理数字参数时遇到了问题。根据文档:

The argument is a term that is used to reference a predicate with N more arguments than the given argument term. For example: call(0) or maplist(1, +).

我了解由数值表示的参数将是用于引用谓词的术语。我不明白的是被引用的谓词如何比参数术语有更多的参数。有人可以更深入地解释数字参数何时适用,或何时适用的示例吗?

这是一个只有知道它的意思才容易理解的公式,可能应该重做。

:-meta_predicate maplist(2, ?, ?).

... 只是表示“2”处的参数将用作将要调用的谓词的内核。我们对此没有特殊的表示法(恕我直言,这是一个很大的错误),因此我们将以标准方式将其写为 f(foo,bar)f(foo)f 等术语。元谓词 maplist/3 将如何处理该术语?好吧,它将在语法上对其进行转换并在其末尾添加“2”个附加参数(并且仅在其末尾,这会导致尴尬):f(foo,bar, ARG1,ARG2),或f(foo, ARG1,ARG2),或f(ARG1,ARG2)然后 maplist/3会调用它。

例如,对于前面提到的 maplist/3,以这个带有两个参数的谓词为例:

myprint(X,Y) 
   :- format("~w\n",[(X,Y)]).

它可以像这样在 maplist/3 调用中使用,不指示任何参数:

maplist(myprint,[0,1,2,3],[a,b,c,d]).

并且两个参数,每个列表中的一个,将附加在术语 myprint 上,然后该术语被封为谓词,并称为:

?- maplist(myprint,[0,1,2,3],[a,b,c,d]).
0,a
1,b
2,c
3,d
true.

这样可以通过 "partially filled-in calls"。 maplist/2 会将 1 个参数附加到第一个参数的末尾,因此可以说:

?- maplist(myprint("foo+"),[a,b,c,d]).
foo+,a
foo+,b
foo+,c
foo+,d
true.

以上内容与 Paulo Moura 的 library(yall) 结合使用,后者将目标包装到匿名谓词中,公开参数。然后可以灵活地重新排列东西

?- maplist([X,Y]>>format("~w\n",[(X,Y)]),[0,1,2,3],[a,b,c,d]).
0,a
1,b
2,c
3,d
true.
?- maplist([Y,X]>>format("~w\n",[(X,Y)]),[0,1,2,3],[a,b,c,d]).
a,0
b,1
c,2
d,3
true.

事实上 library(yall) 为 ISO 标准中严重缺失的 Lambda 表达式提供了正确的语法,以明确显示缺失的参数。

很久以前就可以想象有这样的表达:

?- maplist(λX.verify(3,X), [1,2,3,4,5]).

或者留在 ASCIIland,比如:

?- maplist(\X.verify(3,X), [1,2,3,4,5]).

但这并没有发生。

元谓词指令指定调用时添加到谓词的参数数量。这是一个简单的例子:

:- meta_predicate foo(2, +).

foo(Pred, X) :-
    call(Pred, X, Y),
    format('~q(~q,~q)~n', [Pred, X, Y]).

some_pred(X, Y) :-
    Y is X + 1.

产生以下结果。如您所见,meta_predicate 指令导致 Pred 参数添加模块(在本例中为 user):

?- foo(some_pred, 5).
user:some_pred(5,6)

与其他语言中的 "closure" 类似的操作可以轻松完成,也可以使用 meta_predicate 指令。例如,我们可以

:-meta_predicate foo2(1). 

foo2(Pred):-
    call(Pred, Y),
    format('~q=~q',[Pred,Y]).

并称它为:

?-foo2(some_pred(5)).