A pair of directives
:- if(:Goal). … :- endif.
will evaluate Goal and, if the goal succeeds, the sentences
if/1 directive and the matching
directive will be processed as usual.
If the evaluation of Goal does not succeed, i.e. fails or raises
an exception, the sentences between the
if/1 directive and the
endif/0 directive are completely ignored, except that any
conditional directives must be properly nested. In particular, term
expansion will not be performed on such ignored sentences and the goals
of any nested conditional directives will not be evaluated.
The full form of conditional compilation directives include
elif/1 and are used as follows
:- if(:Goal1). … :- else. … :- endif.
If the goal of the
if/1 directive succeeds, the sentences up
to the matching
else/0 directive are processed as usual.
Otherwise, if the goal fails or raises an exception, the sentences between
else/0 directive and the matching
endif/0 directive are
processed as usual.
elif/1 is available as a shorthand for nested uses of
:- if(:Goal1). … :- elif(:Goal2). … :- elif(:Goal3). … :- else. … :- endif.
will evaluate the goals in turn, until one of them succeeds in which
case the following sentences will be processed as usual up to the
A valid sequence of conditional compilation directives
must contain exactly one
if/1 directive followed by zero or more
elif/1 directives followed by at most one
followed by exactly one
endif/0 directive. Valid sequences of
conditional directives can be nested.
All directives that make up a sequence of conditional compilation
directives must be in the same file. For instance, you cannot have a
if/1 directive in one file and then have the corresponding
endif/0 directive in a file included with an
directive. Nested conditional compilation sequences can of course be
located in included files.
Conditional compilation directives are handled very early in the
processing of an input file. In particular, term expansion hooks will
directives. Also, neither of
endif/0 are defined as predicates.
If evaluation of a goal for
if/1 directive or an
directive raises an exception, an error message will be written and the goal
will be treated as if it failed.
Conditional compilation is useful for writing portable Prolog code
since it makes it possible to adapt to peculiarities of various
implementations. The Prolog flag
dialect, used by several
Prolog implementations, is especially useful here.
:- if(current_prolog_flag(dialect, sicstus). %% We are being compiled in SICStus %% Only SICStus has this library :- use_module(library(process), [process_create/2]). :- elif(current_prolog_flag(dialect, othervendor)). %% We are being compiled in Other Vendor, we need to provide our own %% compatibility layer :- use_module(...). process_create(A,B) :- ... :- else. %% We are being compiled in some unknown Prolog, give up. process_create(_,_) :- throw(not_implemented). :- endif.
Another possible usage is for disabling, perhaps costly, debugging code when building an optimized version of the code.
%% Only need environ/2 at compile-time for conditional compilation :- load_files(library(system), [when(compile_time), imports([environ/2])]). :- if(\+ environ(optimize, true)). %% This clause does some expensive sanity checks. Disabled when building %% an optimized version. foo(X) :- \+ valid_x(X), throw(invalid_x(X)). :- endif. %% This clause is always present. foo(X) :- do_x_things(X).
Invoking the SICStus development system with an option
-Doptimize=true, to set the system property
and then compiling the above code will ensure that the first, sanity
checking, clause is not part of the
foo/1 predicate. Invoking the
development system without such an option will ensure that the sanity
checking clause is part of the