2

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

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

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

参数是一个术语,用于引用比给定参数术语多 N 个参数的谓词。例如:call(0) 或 maplist(1, +)。

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

4

2 回答 2

3

只有当人们知道它的含义时,它才易于理解,并且可能应该重做。

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

...只是意味着“2”位置上的参数将用作将被调用的谓词的内核。我们对此没有特殊的符号(恕我直言,这是一个很大的错误),因此我们将以标准方式将其写为f(foo,bar), 或f(foo), or之类的术语f。元谓词将maplist/3如何处理该术语?好吧,它将在语法上对其进行转换并在其末尾添加“2”个附加参数(并且仅在其末尾,这会导致尴尬):f(foo,bar, ARG1,ARG2), or f(foo, ARG1,ARG2), or 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.

这允许一个人通过“部分填写的电话”。maplist/2会将 1 个参数添加到其第一个参数的末尾,因此可以说:

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

以上内容与 Paulo Moura's 结合使用实际上可以使用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]).

但它没有发生。

于 2020-03-29T00:56:32.770 回答
3

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

:- 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)

类似于其他语言中的“闭包”的东西可以很容易地完成,也可以使用 meta_predicate 指令。例如,我们可以有

:-meta_predicate foo2(1). 

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

并称之为:

?-foo2(some_pred(5)).
于 2020-03-29T01:18:38.393 回答