Стандартный порядок терминов (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одинаковые термины, тоXterm_precedesY
иYterm_precedesXоба ложные.Если
XиYимеют разные типы:Xterm_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.