Как Вы делаете вложенный оператор if-else в Prolog?

Если у меня есть эта функция:

min(List1, List2, Output) :-
   length(List1, N),
   length(List2, M),
   (   N < M ->
       Output = 'true'
   ;   Output = 'false'
   ).

но что, если бы я хотел также проверить, если N == M? Может быть, так:

min(List1, List2, Output) :-
   length(List1, N),
   length(List2, M),
   (   N < M ->
       Output = 'true'
   ;   (  N = M ->
          Output = 'equal'
       ;  Output = 'other'
       )
   ).

не работает.

2 ответов


ваше гнездование импликации (->) выглядит правильно здесь. Обратите внимание, что в вашем определении N и M будут целыми числами (при условии, что звонки length/2 оба успеха), поэтому можно сравнить с == вместо унификации (=). Фактически, вы даже можете использовать арифметические равенства в SWI-PROLOG, а именно =:=:

min(List1, List2, Output) :-
    length(List1, N),
    length(List2, M),
    (N < M ->
        Output = 'true'
    ;   (N =:= M ->
            Output = 'equal'
        ;   Output = 'other'
        )
    ).

тестирование:

1 ?- min([a],[b],O).
O = equal.

2 ?- min([a,c],[b],O).
O = other.

3 ?- min([a,c],[b,d],O).
O = equal.

4 ?- min([a,c],[b,d,e],O).
O = true.

во вложенном if-then-else обычно опускаются избыточные круглые скобки, что дает:

min(List1, List2, Output) :-
    length(List1, N),
    length(List2, M),
    (   N < M -> Output = true
    ;   N =:= M -> Output = equal
    ;   Output = other
    ).

в Prolog, это хорошая практика, чтобы использовать шаблоны когда это возможно, потому что это дает более общие, более декларативные и более читаемые программы, чем использование if-then-else. Для этого конкретного случая условий проверьте compare/3 библиотека сказуемого. compare/3 позволяет вам reify отношение двух длин в атом, и вы можете использовать этот атом для описания три условия с сопоставлением шаблонов:

lists_output(List1, List2, Output) :-
        length(List1, L1),
        length(List2, L2),
        compare(Order, L1, L2),
        order_output(Order, Output).

order_output(<, true).
order_output(=, equal).
order_output(>, other).

примеры запросов и результаты:

?- lists_output([_,_], [_,_,_], Output).
Output = true.

?- lists_output([_,_,_], [_,_,_], Output).
Output = equal.

?- lists_output([_,_,_,_], [_,_,_], Output).
Output = other.