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
Prolog program actually is big condition for "if" with "then" which prints "Goal is reached" and "else" which prints "No sloutions was found". A, B
means "A is true and B is true", most of prolog systems will not try to satisfy "B" if "A" is not reachable (i.e. X=3, write('X is 3'),nl
will print 'X is 3' when X=3, and will do nothing if X=2).
First, let's recall some classical first order logic:
"If P then Q else R" is equivalent to "(P and Q) or (non_P and R)".
Let's take the following concrete example:
If
X
is a member of list[1,2]
thenX
equals2
elseX
equals4
.
We can match above pattern ("If P then Q else R") if ...
P
is list_member([1,2],X)
,non_P
is non_member([1,2],X)
,Q
is X=2
, andR
is X=4
.To express list (non-)membership in a pure way, we define:
list_memberd([E|Es],X) :- ( E = X ; dif(E,X), list_memberd(Es,X) ). non_member(Es,X) :- maplist(dif(X),Es).
Let's check out different ways of expressing "if-then-else" in Prolog!
(P,Q ; non_P,R)
?- (list_memberd([1,2],X), X=2 ; non_member([1,2],X), X=4). X = 2 ; X = 4. ?- X=2, (list_memberd([1,2],X), X=2 ; non_member([1,2],X), X=4), X=2. X = 2 ; false. ?- (list_memberd([1,2],X), X=2 ; non_member([1,2],X), X=4), X=2. X = 2 ; false. ?- X=4, (list_memberd([1,2],X), X=2 ; non_member([1,2],X), X=4), X=4. X = 4. ?- (list_memberd([1,2],X), X=2 ; non_member([1,2],X), X=4), X=4. X = 4.
Correctness score 5/5. Efficiency score 3/5.
(P -> Q ; R)
?- (list_memberd([1,2],X) -> X=2 ; X=4). false. % WRONG ?- X=2, (list_memberd([1,2],X) -> X=2 ; X=4), X=2. X = 2. ?- (list_memberd([1,2],X) -> X=2 ; X=4), X=2. false. % WRONG ?- X=4, (list_memberd([1,2],X) -> X=2 ; X=4), X=4. X = 4. ?- (list_memberd([1,2],X) -> X=2 ; X=4), X=4. false. % WRONG
Correctness score 2/5. Efficiency score 2/5.
(P *-> Q ; R)
?- (list_memberd([1,2],X) *-> X=2 ; X=4). X = 2 ; false. % WRONG ?- X=2, (list_memberd([1,2],X) *-> X=2 ; X=4), X=2. X = 2 ; false. ?- (list_memberd([1,2],X) *-> X=2 ; X=4), X=2. X = 2 ; false. ?- X=4, (list_memberd([1,2],X) *-> X=2 ; X=4), X=4. X = 4. ?- (list_memberd([1,2],X) *-> X=2 ; X=4), X=4. false. % WRONG
Correctness score 3/5. Efficiency score 1/5.
(Preliminary) summary:
(P,Q ; non_P,R)
is correct, but needs a discrete implementation of non_P
.
(P -> Q ; R)
loses declarative semantics when instantiation is insufficient.
(P *-> Q ; R)
is "less" incomplete than (P -> Q ; R)
, but still has similar woes.
Luckily for us, there are alternatives:
Enter the logically monotone control construct if_/3
!
We can use if_/3 together with the reified list-membership predicate memberd_t/3 like so:
?- if_(memberd_t(X,[1,2]), X=2, X=4). X = 2 ; X = 4. ?- X=2, if_(memberd_t(X,[1,2]), X=2, X=4), X=2. X = 2. ?- if_(memberd_t(X,[1,2]), X=2, X=4), X=2. X = 2 ; false. ?- X=4, if_(memberd_t(X,[1,2]), X=2, X=4), X=4. X = 4. ?- if_(memberd_t(X,[1,2]), X=2, X=4), X=4. X = 4.
Correctness score 5/5. Efficiency score 4/5.
Prolog predicates 'unify' -
So, in an imperative langauge I'd write
function bazoo(integer foo)
{
if(foo == 5)
doSomething();
else
doSomeOtherThing();
}
In Prolog I'd write
bazoo(5) :- doSomething.
bazoo(Foo) :- Foo =/= 5, doSomeOtherThing.
which, when you understand both styles, is actually a lot clearer.
"I'm bazoo for the special case when foo is 5"
"I'm bazoo for the normal case when foo isn't 5"
( A == B ->
writeln("ok")
;
writeln("nok")
),
The else part is required
A standard prolog predicate will do this.
isfive(5).
will evaluate to true if you call it with 5 and fail(return false) if you run it with anything else. For not equal you use \=
isNotEqual(A,B):- A\=B.
Technically it is does not unify, but it is similar to not equal.
Learn Prolog Now is a good website for learning prolog.
Edit: To add another example.
isEqual(A,A).
The best thing to do is to use the so-called cuts
, which has the symbol !
.
if_then_else(Condition, Action1, Action2) :- Condition, !, Action1.
if_then_else(Condition, Action1, Action2) :- Action2.
The above is the basic structure of a condition function.
To exemplify, here's the max
function:
max(X,Y,X):-X>Y,!.
max(X,Y,Y):-Y=<X.
I suggest reading more documentation on cuts, but in general they are like breakpoints.
Ex.: In case the first max
function returns a true value, the second function is not verified.
PS: I'm fairly new to Prolog, but this is what I've found out.