Стандартный порядок терминов (ISO/IEC 13211-1 7.2 Порядок терминов) определяется для всех терминов, включая переменные. Несмотря на то, что для этого есть хорошие применения - подумайте о реализации setof/3
, это делает многие в остальном чистые и логичные использования встроенных в 8.4 терминов сравнения декларативным кошмаром со всеми импами (краткой формой для императивных конструкций). 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) определяет, будет ли
не терминX
термин предшествует терминуY
Если
X
иY
одинаковые термины, тоX
term_precedesY
иY
term_precedesX
оба ложные.Если
X
иY
имеют разные типы:X
term_precedesY
если
Тип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
:а) Должна быть ошибка установления, когда
аргумент или один из его компонентов является переменной, и
требуется конкретный аргумент или компонент. Она имеет
форма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
и (\=)/2
проходят через термин внутренне, но накладные расходы для этого чрезвычайно низки по сравнению с явным обходом с (=..)/2
или functor/3, arg/3
.