标准术语顺序(ISO/IEC 13211-1 7.2 术语顺序)适用于所有术语,包括变量。虽然这样做有好处——可以考虑实现setof/3
,但这会使得8.4术语比较中许多本来干净、逻辑清晰的内置函数使用变得混乱不堪,到处都是命令式结构的影响(简称为imps)。8.4术语比较功能包括:
8.4 术语比较
8.4.1 (@=<)/2, (==)/2, (==)/2, (@<)/2, (@>)/2,
(@>=)/2.
8.4.2 compare/3.
8.4.3 sort/2.
8.4.4 keysort/2.
举个例子,考虑以下内容:
?- X @< a.
true.
这是成功的,因为
7.2 术语顺序
一个排序 term_precedes (3.181) 定义了一个术语
X
是否在术语Y
之前。如果
X
和Y
是相同的术语,则X
term_precedesY
和Y
term_precedesX
都为 false。如果
X
和Y
具有不同的类型:则当以下顺序中X
的类型在Y
的类型之前时,X
term_precedesY
:
variable
在floating point
之前,在integer
之前,在atom
之前,在compound
之前。注意 —— 测试术语顺序的内置谓词定义在8.4中。
...
因此,所有变量都比 a
小。但是一旦实例化 X
:
?- X @< a, X = a.
X = a.
结果变得无效。
所以这就是问题。为了克服这个问题,人们可以使用约束条件,或者坚持核心行为,因此产生一个instantiation_error
。
7.12.2 错误分类
错误根据
Error_term
的形式进行分类:a) 当参数或其组件为变量,并且需要实例化参数或组件时,应出现实例化错误。它的形式为
instantiation_error
。
通过这种方式,我们可以确定只要没有发生实例化错误,结果就是明确定义的。
对于(\==)/2
,已经有dif/2
使用约束条件或dif_si/2
(以前是iso_dif/2
)产生一个干净的实例化错误。
dif_si(X, Y) :-
X \== Y,
( X \= Y -> true
; throw(error(instantiation_error,dif_si/2))
).
我的问题是如何定义(和命名)ISO Prolog中相应的安全术语比较谓词?最好不需要任何显式的术语遍历。可能需要澄清的是:上面的 dif_si/2 不使用任何显式的术语遍历。(\==)/2 和 (\=)/2 都在内部遍历术语,但与使用 (=..)/2 或 functor/3、arg/3 进行显式遍历相比,开销极低。请保留HTML标签。
freeze/2
有什么问题吗? - user1812457freeze/2
将无法正常工作,您还需要在?=
与when/2
一起使用。例如:lt(X+2, Y+1), X = Y
应该已经失败了。 - false