maplist/3谓词的格式如下
maplist(:Goal, ?List1, ?List2)
然而,非常相似的函数findall/3具有
形式findall(+Template, :Goal, -Bag)
它不仅有目标,还有模板。我发现这个模板在很多地方非常有用,并开始想知道为什么maplist / 3没有。
为什么maplist / 3没有模板参数,而findall / 3呢?这些谓词之间的显着区别是什么?
答案 0 :(得分:4)
findall/3
,setof/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).
(请注意,我避免调用此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它是一个列表构造函数,它的目标终止和(我看到)必需品是必不可少的指出保留每个成功目标调用的内容。