unificacion swi reglas programas predicados logica ejemplos corte conocimiento prolog prolog-dif

swi - ¿Cuáles son los usos del predicado de falla en Prolog?



reglas en prolog (4)

No puedo llegar a una situación en la que lo necesite.


Otro uso para fallar es forzar el retroceso a través de alternativas cuando se usan predicados con efectos secundarios:

writeall(X) :- member(A,X), write(A), fail. writeall(_).

Sin embargo, algunas personas podrían no considerar este estilo de programación particularmente bueno. :)


Un caso (tomado de la Programación de lógica de restricción con Eclipse ) es una implementación de no / 1:

:- op(900, fy, not). not Q :- Q, !, fail. not _ .

Si Q tiene éxito, el corte (!) Hace que la segunda cláusula no se descarte, y la falla asegura un resultado negativo. Si Q falla, entonces la segunda cláusula no se dispara primero.


Fallo explícito. fail se utiliza a menudo junto con cut: ... !, fail. para hacer cumplir el fracaso.

Para todas las construcciones. El uso explícito de fail / false para enumerar a través del seguimiento es una actividad muy propensa a errores. Considere un caso:

... ( generator(X), action(X), fail ; true ), ...

La idea es, pues, "hacer" la acción para todo X Pero, ¿qué pasa si falla la action(X) ? Esta construcción simplemente continúa con el próximo candidato, como si nada hubiera pasado. De esta manera, ciertos errores pueden permanecer sin ser detectados por mucho tiempo.

Para tales casos, es mejor utilizar /+ ( generator(X), /+ action(X) ) que falla, si la action(X) falla para alguna X Algunos sistemas ofrecen esto como un incorporado para todos forall/2 . Personalmente, prefiero usar /+ en este caso porque el /+ es un poco más claro que la construcción no deja un enlace.

Corte de falla. Para fines de diagnóstico, a menudo es útil agregar a propósito false en sus programas. Vea failure-slice de failure-slice para más detalles.


Los sistemas elegantes proporcionan false/0 como sinónimo declarativo del imperativo fail/0 . Un ejemplo en el que es útil es cuando se quiere forzar manualmente el retroceso de los efectos secundarios, como:

?- between(1,3,N), format("line ~w/n", [N]), false. line 1 line 2 line 3

En lugar de false/0 , también puede usar cualquier objetivo que falle, por ejemplo, un poco más corto:

?- between(1,3,N), format("line ~w/n", [N]), 0=1. line 1 line 2 line 3

Por lo tanto, false/0 no es estrictamente necesario pero es bastante bueno.

EDITAR : A veces veo principiantes que desean decir, por ejemplo, "mi relación no es válida para la lista vacía", y luego agrego:

my_relation([]) :- false.

a su código. Esto no es necesario, y no es un buen ejemplo de uso de false/0 , excepto por ejemplo en segmentos de falla que se generan mediante programación. En su lugar, concéntrate en declarar las cosas que se sostienen sobre tu relación. En este caso, simplemente omita la cláusula completa y defina la relación solo para las listas que no estén vacías, es decir, tenga al menos un elemento:

my_relation([L|Ls]) :- etc.

o, si también está describiendo otros términos además de las listas, use una restricción como:

my_relation(T) :- dif(T, []), etc.

Dada solo una de estas dos cláusulas (o incluso ambas), la consulta ?- my_relation([]). fallará automáticamente. No es necesario introducir una cláusula adicional que nunca tiene éxito para ese propósito.