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