There is an efficiency advantage in using conditionals whose test part
consists only of arithmetic comparisons or type tests.  Consider the
following alternative definitions of the predicate
type_of_character/2.  In the first definition, four clauses
are used to group characters on the basis of arithmetic comparisons.
     type_of_character(Ch, Type) :-
             Ch >= "a", Ch =< "z",
             !,
             Type = lowercase.
     type_of_character(Ch, Type) :-
             Ch >= "A", Ch =< "Z",
             !,
             Type = uppercase.
     type_of_character(Ch, Type) :-
             Ch >= "0", Ch =< "9",
             !,
             Type = digit.
     type_of_character(_Ch, Type) :-
             Type = other.
   In the second definition, a single clause with a conditional is used. The compiler generates equivalent, optimized code for both versions.
     type_of_character(Ch, Type) :-
             (   Ch >= "a", Ch =< "z" ->
                     Type = lowercase
             ;   Ch >= "A", Ch =< "Z" ->
                     Type = uppercase
             ;   Ch >= "0", Ch =< "9" ->
                     Type = digit
             ;   otherwise ->
                     Type = other
             ).
   Following is a list of built-in predicates that are compiled efficiently in conditionals:
atom/1
atomic/1
callable/1
compound/1
float/1
ground/1
integer/1
nonvar/1
number/1
simple/1
var/1
</2
=</2
=:=/2
=\=/2
>=/2
>/2
@</2
@=</2
==/2
\==/2
@>=/2
@>/2
This optimization is actually somewhat more general than what is described above. A sequence of guarded clauses:
     Head1 :- Guard1, !, Body1.
     ...
     Headm :- Guardm, !, Bodym.
     Headn :- Bodym.
   is eligible for the same optimization, provided that the arguments of the clause heads are all unique variables and that the “guards” are simple tests as listed above.