2010-11-16 40 views
7

Si tengo esta función:¿Cómo se hace una declaración Anide if-else en Prolog?

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

pero lo que si quería comprobar también si N == M? Tal vez así:

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

Parece que no funciona.

+0

¿Qué, exactamente , no parece funcionar? ¿Recibes respuestas que no esperas o no compila? – sharky

Respuesta

5

Su anidación de implicación (->) parece correcta aquí. Tenga en cuenta que, en su definición, N y M serán enteros (suponiendo que las llamadas a length/2 tienen éxito), por lo que se pueden comparar con == en lugar de unificación (=). De hecho, incluso se podría utilizar la aritmética es igual en SWI-Prolog, a saber, =:=:

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

Pruebas:

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

En anidada if-then-else, es común omitir paréntesis redundantes, obteniéndose:

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

En Prolog, es una buena práctica de usar coincidencia de patrones cuando sea posible, ya que esto produce más general, más Decla programas más fáciles de leer que usar if-then-else. Para este caso particular de condiciones, consulte el predicado de biblioteca compare/3. compare/3 le permite Reify la relación de las dos longitudes en un átomo, y se puede utilizar ese átomo para describir las tres condiciones con la coincidencia de modelos:

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

consultas de ejemplo y resultados:

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

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

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

Muy bien, me gusta este estilo, es más nítido. Me pregunto si las reglas de precedencia del operador para '->', ';', etc. son comunes entre otras implementaciones de PROLOG tales que esto no es específico de SWI-PROLOG (probablemente el caso)? – sharky

+0

@Sharky, no tengo un estándar ISO listo, pero he visto este estilo antes y el código de @ mat funciona perfectamente en SICStus 3.12. –

+2

@larsmans: El ejemplo usa solo operadores predefinidos de ISO. Ver [tag: iso-prolog] para saber cómo obtener el estándar por USD 30! – false

Cuestiones relacionadas