标准术语顺序仅将变量视为句法对象。因此,除了其他问题之外,sort/2
打破了关系定义的常见假设。替换也不能保证解决方案,第二个参数的地面实例也没有排序。
?- X = 1, sort([1,X],[1]).
X = 1.
?- sort([1,X],[1]). % generalization fails
false.
?- sort([1,X],[2,1]).
X = 2. % unsorted list succeeds
?- X = 2, sort([1,X],[2,1]). % answer substitution fails
false.
但是即使我们忽略了声明性的问题,我们仍然面临这样一个问题:只有在创建排序列表期间变量的顺序才保持不变。因此,根据变量的“年龄”,我们会得到
?- _=X+Y, sort([X,Y],[2,1]).
X = 2, Y = 1.
?- _=Y+X, sort([X,Y],[2,1]).
Y = 2, X = 1.
年龄可能随时间而改变,甚至相对年龄也是如此。
我们确实应该受到所有这种不稳定行为的保护。
到目前为止,我尝试了一个安全的定义,它产生与 sort/2
相同类型的错误,但当要排序的列表不是ground时会产生实例化错误。 只要没有出现实例化错误,这个定义就是完美的。
sort_si(List, Sorted) :-
sort(List, ISorted),
( sort([], [_|Sorted]) ; true ), % just to get the type_error
( ground(ISorted)
-> Sorted = ISorted
; throw(error(instantiation_error, _Imp_def))
).
?- sort_si([X,X],S).
caught: error(instantiation_error, _97) % unexpected; expected: S = [X]
?- sort_si([-X,+Y], S).
caught: error(instantiation_error, _97) % unexpected; expected: S = [+Y,-X]
?- sort_si([_,_], []).
caught: error(instantiation_error, _97) % unclear, maybe failure
我的问题是:如何通过减少不必要的实例化错误来改进ISO Prolog中的这个定义?理想情况下,只有当
sort(List, Sorted)
的实例具有不同的结果时,才会对sort_si(List, Sorted)
出现实例化错误。并不需要最优数量的实例化错误。也许可以在某种程度上利用排序后的列表ISorted
的事实。另外,由于现在不存在未排序的ground list解决方案,因此Sorted
可以被认为是已排序的。
sort_si([X,a], [a]), X = a.
失败了,然而X = a, sort_si([X,a], [a]).
成功了。这种情况应该通过发出适当的实例化错误来避免。 - falseSorted \= ISorted
,这意味着实例化错误优先于失败,这似乎是有道理的。 - jnmonettesort_si([X,a], [n,importe])
会产生一个错误,这很遗憾。不过(仅仅为了这个目的),我们也可以对结果进行排序检查! - falsesort([a|_],[n,importe])
会产生错误一样,如果它首先检查输出参数,它也可能失败。 - jnmonette