为什么maplist / 3没有使用模板?

时间:2018-01-03 17:12:58

标签: prolog meta-predicate

maplist/3谓词的格式如下

maplist(:Goal, ?List1, ?List2)

然而,非常相似的函数findall/3具有

形式
findall(+Template, :Goal, -Bag)

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

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

3 个答案:

答案 0 :(得分:4)

findall/3setof/3bagof/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).

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

一般来说,我宁愿避免制作我自己的模板"因为这很容易引起误解(已经在我和我之间):论证不是人们通常期待的纯粹的关系论证。通过使用(\)/1代替,局部变量可以更好地处理,并且因为特殊而更加明显。

......啊,还有另一个很好的理由来避免使用模板:它们实际上迫使你总是把一些不那么真实的机制作为复制考虑在内。这意味着您的程序可能会暴露一些异常情况。单调性。你真的要看看细节。

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

答案 1 :(得分:2)

考虑您的具体示例将明确为什么playFirework.call(this); 不需要模板:

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

例如,您可以编写谓词:

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

现在,您的示例完全符合预期,无需模板:

?- maplist(p(1), [1,2,3,4], [0,-1,-2,-3]).
true.

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

答案 2 :(得分:2)

  

这些谓词之间有什么显着差异?

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

在maplist / N中,没有任何关于谓词的确定性的假设,因为执行流程是由列表模式控制的。 findall / 3它是一个列表构造函数,它的目标终止和(我看到)必需品是必不可少的指出保留每个成功目标调用的内容。