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
db_reference/1
float/1
ground/1
integer/1
nonvar/1
mutable/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.