Как определить (и назвать) соответствующие предикаты сравнения безопасных терминов в ISO Prolog?
Стандартный порядок терминов (ISO / IEC 13211-1 7.2 Порядок терминов) определяется для всех терминов, включая переменные. Хотя для этого есть хорошее применение - подумайте о реализацииsetof/3
, это делает многие иначе понятные и логичные использования встроенных в 8.4 Term сравнений декларативным кошмаром со всеми бесами (краткой формой для императивных конструкций). 8.4 Срок сравнения функций:
8.4.1 (@ = <) / 2, (==) / 2, (\ ==) / 2, (@ <) / 2, (@>) / 2, (@> =) / 2.
8.4.2 сравнить / 3.
8.4.3 сортировать / 2.
8.4.4 keysort / 2.
Чтобы привести пример, рассмотрим:
?- X @< a.
true.
Это удается, потому что
7.2 Срок заказаЗаказterm_precedes (3.181) определяет, является ли или
не терминX
термин предшествует терминуY
.
ЕслиX
а такжеY
одинаковые термины тогдаX
term_precedes Y
а такжеY
term_precedes X
оба ложные.
Если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
.
Ошибки классифицируются по форме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 Пролог? В идеале, без какого-либо явного обхода термина. Может быть, чтобы уточнить: вышеiso_dif/2
не использует какой-либо явный термин обход. И то и другое(\==)/2
а также(\=)/2
пройти через термин внутри, но накладные расходы для этого чрезвычайно низки по сравнению с явным обходом с(=..)/2
или жеfunctor/3, arg/3
.