Существуют три различных способа выражения чего-то вроде if-then-else в Прологе. Для сравнения рассмотрим char_class/2
. Для a
и b
класс должен быть ab
и other
для всех других терминов. Можно написать это неуклюже так:
char_class(a, ab).
char_class(b, ab).
char_class(X, other) :-
dif(X, a),
dif(X, b).
?- char_class(Ch, Class).
Ch = a, Class = ab
; Ch = b, Class = ab
; Class = other,
dif(Ch, a), dif(Ch, b).
Чтобы написать вещи более компактно, необходима конструкция if-then-else. Пролог имеет встроенный:
?- ( ( Ch = a ; Ch = b ) -> Class = ab ; Class = other ).
Ch = a, Class = ab.
Хотя этот ответ звучит здраво, он неполон. Только первый ответ от ( Ch = a ; Ch = b )
дается. Другие ответы отрублены. Действительно, не очень реляционный.
Лучшая конструкция, часто называемая «мягким срезом» (не верьте названию, «срез - это срез»), дает несколько лучшие результаты (это в YAP):
?- ( ( Ch = a ; Ch = b ) *-> Class = ab ; Class = other ).
Ch = a, Class = ab
; Ch = b, Class = ab.
В качестве альтернативы, SICStus имеет if/3
с очень похожей семантикой:
?- if( ( Ch = a ; Ch = b ), Class = ab , Class = other ).
Ch = a, Class = ab
; Ch = b, Class = ab.
Таким образом, последний ответ все еще скрыт. Теперь введите library(reif)
для SICStus , YAP и SWI . Установите его и скажите:
?- use_module(library(reif)).
?- if_( ( Ch = a ; Ch = b ), Class = ab , Class = other ).
Ch = a, Class = ab
; Ch = b, Class = ab
; Class = other,
dif(Ch, a), dif(Ch, b).
Обратите внимание, что все if_/3
скомпилированы в дико вложенный if-then-else для
char_class(Ch, Class) :-
if_( ( Ch = a ; Ch = b ), Class = ab , Class = other ).
, который расширяется в YAP 6.3.4 до:
char_class(A,B) :-
( A\=a
->
( A\=b
->
B=other
;
( A==b
->
B=ab
)
;
A=b,
B=ab
;
dif(A,b),
B=other
)
;
( A==a
->
B=ab
)
;
A=a,
B=ab
;
dif(A,a),
( A\=b
->
B=other
;
( A==b
->
B=ab
)
;
A=b,
B=ab
;
dif(A,b),
B=other
)
).