4

maplist /3谓词具有以下形式

maplist(:Goal, ?List1, ?List2)

然而,非常相似的函数findall/3具有以下形式

findall(+Template, :Goal, -Bag)

它不仅有一个目标,还有一个模板。我发现这个模板在很多地方都非常有用,并开始怀疑为什么 maplist/3 没有。

为什么 maplist/3 没有模板参数,而 findall/3 有?这些谓词之间的显着区别是什么?

4

3 回答 3

5

findall/3setof/3和中的模板bagof/3是尝试使用 Prolog 的变量来模拟正确的量化。大多数时候(在所有三种情况下)它们都涉及在模板中显式复制这些术语。

因为maplist/3这种机制并不总是必要的,因为这里的实际量化只是关于列表的元素。通常,不会发生进一步的修改。的第一个参数不是使用模板,而是maplist/3一个不完整的目标,缺少两个进一步的参数。

maplist(Goal_2, Xs, Ys).

如果您坚持,您可以使用以下方法获得您的模板版本library(lambda)

templmaplist(Template1, Template2, Goal_0, Xs, Ys) :-
   maplist(\Template1^Template2^Goal_0, Xs, Ys).

(请注意,我避免调用 this maplist/5,因为这已经定义了另一种含义)

一般来说,我宁愿避免制作“我自己的模板”,因为这很容易导致误解(已经在我和我之间):这些论点不是人们通常期望的纯粹的关系论点。通过(\)/1改用,局部变量可以更好地处理,并且更明显更特别。

... 啊,还有另一个避免使用模板的好理由:它们实际上迫使您始终考虑一些不太纯正的机制作为复制。这意味着您的程序可能会暴露一些单调性异常。你真的必须仔细研究细节。

另一方面,如果没有模板,只要不涉及复制,即使您的高阶谓词也会像魅力一样保持单调性。

于 2018-01-04T00:55:37.023 回答
3

考虑您的具体示例将清楚为什么不需要模板maplist/3

Inmaplist/N和其他高阶谓词,您可以使用currying来修复特定参数。

例如,您可以编写谓词:

p(Z,X,Y):-
        Z #= X + Y。

现在您的示例完全按预期工作,无需模板:

?- maplist( p(1) , [1,2,3,4], [0,-1,-2,-3])。
真的。

您可以使用library(lambda)动态重新排序参数,以使其更加灵活。

于 2018-01-03T17:42:09.193 回答
2

这些谓词之间的显着区别是什么?

findall/3(和family,setof/3 和bagof/3)不能在纯Prolog(没有副作用的单调子集)中实现,而maplist/N 只是一种“宏”,实现样板列表访问.

在 maplist/N 中,没有假设谓词的确定性,因为执行流程由列表模式控制。findall/3 它是一个列表构造函数,它是目标终止的必要条件,并且(我明白)有必要指出每个成功的目标调用要保留的内容。

于 2018-01-04T11:03:15.657 回答