Is there a way to do an if in prolog, e.g. if a variable is 0, then to do some actions (write text to the terminal). An else isn\'t even needed, but I can\'t find any docume
I found this helpful for using an if statement in a rule.
max(X,Y,Z) :-
( X =< Y
-> Z = Y
; Z = X
).
Thanks to http://cs.union.edu/~striegnk/learn-prolog-now/html/node89.html
Yes, there is such a control construct in ISO Prolog, called ->
. You use it like this:
( condition -> then_clause ; else_clause )
Here is an example that uses a chain of else-if-clauses:
( X < 0 ->
writeln('X is negative. That's weird! Failing now.'),
fail
; X =:= 0 ->
writeln('X is zero.')
; writeln('X is positive.')
)
Note that if you omit the else-clause, the condition failing will mean that the whole if-statement will fail. Therefore, I recommend always including the else-clause (even if it is just true
).
You should read Learn Prolog Now! Chapter 10.2 Using Cut. This provides an example:
max(X,Y,Z) :- X =< Y,!, Y = Z.
to be said,
Z
is equal to Y
IF !
is true (which it always is) AND X
is <= Y
.
There are essentially three different ways how to express something like if-then-else in Prolog. To compare them consider char_class/2
. For a
and b
the class should be ab
and other
for all other terms. One could write this clumsily like so:
char_class(a, ab).
char_class(b, ab).
char_class(X, other) :-
dif(X, a),
dif(X, b).
?- char_class(Ch, Class).
Ch = a, Class = ab
; Ch = b, Class = ab
; Class = other,
dif(Ch, a), dif(Ch, b).
To write things more compactly, an if-then-else construct is needed. Prolog has a built-in one:
?- ( ( Ch = a ; Ch = b ) -> Class = ab ; Class = other ).
Ch = a, Class = ab.
While this answer is sound, it is incomplete. Just the first answer from ( Ch = a ; Ch = b )
is given. The other answers are chopped away. Not very relational, indeed.
A better construct, often called a "soft cut" (don't believe the name, a cut is a cut is a cut), gives slightly better results (this is in YAP):
?- ( ( Ch = a ; Ch = b ) *-> Class = ab ; Class = other ).
Ch = a, Class = ab
; Ch = b, Class = ab.
Alternatively, SICStus has if/3
with very similar semantics:
?- if( ( Ch = a ; Ch = b ), Class = ab , Class = other ).
Ch = a, Class = ab
; Ch = b, Class = ab.
So the last answer is still suppressed. Now enter library(reif)
for SICStus, YAP, and SWI. Install it and say:
?- use_module(library(reif)).
?- if_( ( Ch = a ; Ch = b ), Class = ab , Class = other ).
Ch = a, Class = ab
; Ch = b, Class = ab
; Class = other,
dif(Ch, a), dif(Ch, b).
Note that all the if_/3
is compiled away to a wildly nested if-then-else for
char_class(Ch, Class) :-
if_( ( Ch = a ; Ch = b ), Class = ab , Class = other ).
which expands in YAP 6.3.4 to:
char_class(A,B) :-
( A\=a
->
( A\=b
->
B=other
;
( A==b
->
B=ab
)
;
A=b,
B=ab
;
dif(A,b),
B=other
)
;
( A==a
->
B=ab
)
;
A=a,
B=ab
;
dif(A,a),
( A\=b
->
B=other
;
( A==b
->
B=ab
)
;
A=b,
B=ab
;
dif(A,b),
B=other
)
).