I seemed to hear the whispered cry, "The horror! The horror!"

(Joseph Conrad,*Heart of Darkness*)

(Joseph Conrad,

The point of this page is to show you where following this streak is likely

A small number of rules suffices to write great Prolog code. Breaking them will result in programs that are defective in one or more ways.

Video: |

- It reports
*wrong*answers. - It
*fails to report*intended solutions.

Suppose a program is defective

The primary means to make your programs defective in the

The primary means to make your programs defective in this way is to use predicates like

solve :- solution(S), format("the solution is: ~q\n", [S]).A major drawback of this approach is that

To benefit from the full generality of relations,

solution(S) :- constraint_1(S), etc.Sometimes, you may want special formatting. In such case, you can still describe the output in a pure way, using for example the nonterminal

Unfortunately, sticking to low-level constructs comes at a high price: It makes the language harder to teach, harder to learn and harder to understand than necessary. It requires students to learn declarative and operational semantics essentially

The primary means to make Prolog harder to teach than necessary is to introduce beginners to low-level predicates for arithmetic like

horror_factorial(0, 1) :- !. horror_factorial(N, F) :- N > 0, N1 is N - 1, horror_factorial(N1, F1), F is N*F1.Observe the horror of

?- horror_factorial(N, F).The version withoutN = 0, F = 1.

horror_factorial(0, 1). horror_factorial(N, F) :- N > 0, N1 is N - 1, horror_factorial(N1, F1), F is N*F1.The horror of low-level language constructs prevails:

?- horror_factorial(N, F). N = 0, F = 1 ;If you accept this, you arecaught: error(instantiation_error,'(is)'/2)

- limited by using outdated language constructs.
- mistaking relations for functions.
- not caring about the most general query.
- preventing declarative debugging by using impure constructs.

Start small. For example, instead of low-level integer arithmetic, use a more declarative alternative:

horror_factorial(0, 1) :- !. horror_factorial(N, F) :- N #> 0, N1 #= N - 1, horror_factorial(N1, F1), F #= N*F1.Still better than nothing. Then, remove the

n_factorial(0, 1). n_factorial(N, F) :- N #> 0, N1 #= N - 1, n_factorial(N1, F1), F #= N*F1.This version also works for the

?- n_factorial(N, F).That's quite good: A few simple changes have led to a quite general logic program.N = 0, F = 1 ; N = 1, F = 1 ; N = 2, F = 2 ; N = 3, F = 6 ; ...

It is ill-directed rebellion to cling to outdated features, for life is not lived backwards nor tarries in yesterday.

Use declarative constructs in your Prolog programs to make them more general while retaining acceptable performance.