2010-11-16 8 views
7

Si j'ai cette fonction:Comment faites-vous une instruction if-else imbriquée dans Prolog?

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

mais si je voulais aussi vérifier si N == M? Peut-être comme ceci:

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

Ne semble pas fonctionner.

+0

Qu'est-ce, exactement , ne semble pas fonctionner? Obtenez-vous des réponses auxquelles vous ne vous attendez pas ou ne compilez-vous pas? – sharky

Répondre

5

Votre imbrication de l'implication (->) semble correcte ici. Notez que, dans votre définition, N et M seront des entiers (en supposant que les appels à length/2 réussissent tous deux), donc peuvent être comparés avec == au lieu de l'unification (=). En fait, vous pouvez même utiliser l'arithmétique est égale à SWI-Prolog, à savoir =:=:

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

Test:

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. 
4

Dans imbriquée if-then-else, il est courant d'omettre les parenthèses redondantes, rendement:

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

En Prolog, il est bon d'utiliser modèle correspondant lorsque cela est possible, car cela donne plus général, plus décla programmes ratifs et plus lisibles que d'utiliser if-then-else. Pour ce cas particulier de conditions, consultez le prédicat de bibliothèque compare/3. compare/3 vous permet de réifier la relation des deux longueurs dans un atome, et vous pouvez utiliser cet atome pour décrire les trois conditions avec correspondance de motif:

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). 

exemples de requêtes et résultats:

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

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

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

Assez sympa, j'aime ce style, c'est plus propre. Je me demande si les règles de priorité d'opérateur pour '->', ';', etc. sont communes parmi d'autres implémentations PROLOG de telle sorte que ce n'est pas spécifique à SWI-PROLOG (probablement le cas)? – sharky

+0

@Sharky, je n'ai pas de norme ISO prête, mais j'ai déjà vu ce style et le code de @ mat fonctionne parfaitement dans SICStus 3.12. –

+2

@larsmans: L'exemple utilise uniquement les opérateurs prédéfinis ISO. Voir [tag: iso-prolog] pour savoir comment obtenir la norme pour 30 USD! – false

Questions connexes