标准术语顺序(ISO/IEC 13211-1 7.2 术语顺序)定义在所有术语上——包括变量。虽然这有很好的用途——想想setof/3
. 8.4 词条比较特点:
8.4 术语比较
8.4.1 (@=<)/2, (==)/2, (\==)/2, (@<)/2, (@>)/2, (@>=)/2。
8.4.2 比较/3。
8.4.3 排序/2。
8.4.4 键排序/2。
举个例子,考虑:
?- X @< a.
true.
这成功了,因为
7.2 期限顺序
排序term_precedes
(3.181) 定义 了 term是否在X
term 之前Y
。如果
X
和Y
是相同的术语,那么X
term_precedesY
和Y
term_precedesX
都是假的。如果
X
和Y
有不同的类型:X
term_precedesY
iff 的
类型按以下顺序在类型之前:X
先于先于先于 先于。Y
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
使用约束或iso_dif/2
产生干净实例化错误的情况。
iso_dif(X, Y) :-
X \== Y,
( X \= Y -> true
; throw(error(instantiation_error,iso_dif/2))
).
那么我的问题是:如何在ISO Prolog中定义(和命名)相应的安全术语比较谓词?理想情况下,没有任何明确的术语遍历。也许要澄清一下:上面iso_dif/2
没有使用任何明确的术语遍历。两者(\==)/2
和在内部遍历该术语,但是与使用or(\=)/2
的显式遍历相比,这样做的开销非常低。(=..)/2
functor/3, arg/3