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 documentation of if.
- 
                    See [if-then-else](http://www.learnprolognow.org/) from www.learnprolognow.org – adamo Jun 12 '11 at 13:32
- 
                    9Prolog has a builtin `if-then-else` syntax. But it is not declarative to really use it. – Willem Van Onsem Aug 22 '14 at 17:12
- 
                    `myFunc(Variable) :- Variable=0,print('OK, here is your text.').` – Topological Sort Apr 14 '23 at 20:20
10 Answers
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).
 
    
    - 15,497
- 4
- 39
- 47
- 
                    18In ISO, the control construct is actually called (;)/2 - if-then-else (7.8.8) because the principal functor is the (;)/2. This is a bit irritating since there is another control construct with the same principal functor: (;)/2 - disjunction (7.8.6). You can see it like this `(if->then;else) == ((if->then);else).` succeeds. – false Feb 17 '12 at 00:29
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). 
 
    
    - 18,536
- 11
- 31
- 47
 
    
    - 6,111
- 23
- 25
- 
                    9+1 for enforcing logic programming style instead of imperative one :-) – Agnius Vasiliauskas Aug 14 '12 at 07:53
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"
- 
                    4
- 
                    @false it probably should do the negation of `Foo is 5` if you want it to simplify numbers like that. – Pro Q Mar 28 '18 at 19:15
- 
                    2
- 
                    1This helped a ton with how to think about the difference between the two styles of programming. Cheers. – Ryan Cocuzzo Sep 06 '20 at 18:32
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)".
How can we express "if-then-else" like that in Prolog?
Let's take the following concrete example:
If
Xis a member of list[1,2]thenXequals2elseXequals4.
We can match above pattern ("If P then Q else R") if ...
- condition Pislist_member([1,2],X),
- negated condition non_Pisnon_member([1,2],X),
- consequence QisX=2, and
- alternative RisX=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.
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
 
    
    - 10,264
- 13
- 101
- 209
 
    
    - 4,672
- 2
- 43
- 48
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 Scryer, 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
      )
   ).
 
    
    - 10,264
- 13
- 101
- 209
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.
- 
                    Not sure why this post was voted down. cold cuts are the most powerful way to handle conditions in prolog. – gaurav.singharoy Jun 02 '14 at 08:49
- 
                    5
- 
                    That `max(X,Y,X):-X>Y,!.` should be setting the 3rd arg *after* the cut, to be steadfast - https://stackoverflow.com/questions/39191184/steadfastness-definition-and-its-relation-to-logical-purity-and-termination – brebs Jun 23 '23 at 10:36
- 
                    @brebs never have I ever thought this post would have received a comment 10 years from its original posting... cheers =D – skipper Jun 25 '23 at 19:29
(  A == B ->
     writeln("ok")
;
     writeln("nok")
),
The else part is required
 
    
    - 2,499
- 1
- 23
- 41
- 
                    2It is certainly a good idea to indicate an else-part, but it is not required. – false Jul 07 '14 at 22:03
Prolog program actually is big condition for "if" with "then" which prints "Goal is reached" and "else" which prints "No sloutions was found". A, Bmeans "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).
 
    
    - 12,457
- 1
- 33
- 41
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.
 
    
    - 1,757
- 3
- 16
- 34
 
     
     
     
     
     
     
    