查看Prolog文档,谓词签名有时写成如下:
foo(:Bar, +Baz, -Qux, ?Mop)
:
,+
,-
和?
是什么?我如何解释它们?此外,这些是唯一存在的还是更多的?
答案 0 :(得分:9)
在此上下文中,这些前缀运算符表示实例化模式,即它们告诉您哪些参数应该是变量或在调用谓词时实例化。他们还会告诉您参数是否(可能进一步)被调用实例化。它们也可以用来告诉你一个参数将以某种方式通过你正在调用的谓词进行元解释。其中一些实例化模式是标准的,其他模式取决于系统。最常见的是:
-
- 参数应该是未绑定的(可能是输出参数)
+
- 参数应绑定(输入参数)
?
- 参数可以是绑定的也可以是未绑定的
@
- 参数不会被调用
:
- 论证将以某种方式进行元解释(通常含糊不清)
0
- 该参数将被解释为目标并被称为
N
- 其中N是自然数;该参数将被解释为一个闭包,它将由N
个附加参数组成,以构建一个将被称为
不同的系统提供其他或不同的实例化模式。例如,用于声明在调用谓词时应该参数,或者声明参数应该是谓词指示符或者将被解释为语法规则体。您需要参考您正在使用的Prolog系统的文档以获取详细信息。
答案 1 :(得分:6)
模式声明最初出现在20世纪70年代末的DECsystem-10编译器中。 DECMSystem-10 1978-09用户指南是最早的描述之一。动机是1982-11-10:
此类信息使编译器能够生成更紧凑的代码 更好地利用运行时存储。节省运行时间 特别是储存通常非常可观。模式 声明还有助于其他人了解你的情况 程序运作。
+
- 参数将始终为非变量
-
- 参数将始终是变量
?
- 没有限制
请注意,这些声明适用于每个目标。最值得注意的是,它们适用于递归目标。以这种方式,以下模式声明及其定义意味着第二个参数不是部分列表。因此,目标member(A, [c|_])
将不符合要求。因此,界面和实现在某种程度上相互依赖,这可能导致相当复杂的情况,因为必须考虑谓词本身执行的统一。
:- mode member(?, +).
member(X, [X|_]). % member(X, [X,.._]) in DEC10
member(X, [_|L]) :-
member(X, L).
如果某个具体目标违反了模式声明,则该声明将被忽略,或者将产生一个错误,该错误在此时意味着写出错误消息并失败。 DECsystem-10解释器总是忽略声明。
在20世纪70年代的深层次,DEC 10用户指南因此对模式声明产生了两种解释:第一种是规定性的,在调用者不满足模式的情况下确实产生错误。第二个是完全非正式的,忽略了运行时的模式声明。前者用于Prolog标准,后者可以在一些Prolog系统的文档中找到。
Prolog标准(ISO / IEC 13211-1:1995,2007,2012)使用以下格式来定义内置谓词。它从子条款.1描述,.2模板和模式,。3错误开始,并且可选地继续.4示例,.5自举内置谓词。
8.1.2模板和模式
参数类型和规则的规范 其中的内置谓词应被实例化 满意。这些案件构成了一个相互排斥的集合。
...
混凝土模式是:
+
- 论证应该被实例化。
@
- 与+
类似,论点保持不变。
-
- 参数应该是一个变量,如果目标成功将被实例化。
?
- 没有模式要求,参数可以是变量或实例化。
如果使用不同模式调用谓词,则会生成instantiation_error
或uninstantiation_error
。如果类型不匹配,则生成type_error
。
通过这种方式,程序员只需查看模板和模式子条款就可以预见到许多错误,而无需阅读详细的错误条件。
与ISO不同的系统在模式的精确解释方面也各不相同。如果类型错误合适,许多人会执行静默失败。他们将模式声明视为一种手段,用于指示谓词预期与未定义含义一起工作的情况。 -
通常大致解释如下。由于没有定义含义的实际参考,这是我非正式地收集的内容:
-
- 参数是“输出参数”。这意味着它将与执行目标后生成的术语统一。所以这个论点是坚定的。通常,这种论证没有错误。
答案 2 :(得分:1)
一个更现代的文档在这里: https://www.swi-prolog.org/pldoc/man?section=modes
对于元谓词也有类似的注释,它们应具有meta_predicate
伪指令,以确保它们在被调用时正确添加了模块。 https://www.swi-prolog.org/pldoc/doc_for?object=(meta_predicate)/1