Meta-call predicates are used to call terms constructed at run time. The basic meta-call mechanism offered by SWI-Prolog is to use variables as a subclause (which should of course be bound to a valid goal at runtime). A meta-call is slower than a normal call as it involves actually searching the database at runtime for the predicate, while for normal calls this search is done at compile time.
call(plus(1), 2,
X)
will call plus/3,
binding X to 3.
The call/[2..] construct is handled by the compiler, which implies that redefinition as a predicate has no effect. The predicates call/[2-6] are defined as true predicates, so they can be handled by interpreted code.
apply(plus(1), [2, X])
will call plus(1, 2, X)
. apply/2
is incorporated in the virtual machine of SWI-Prolog. This implies that
the overhead can be compared to the overhead of call/1.
New code should use call/[2..] if the length of
List is fixed, which is more widely supported and faster
because there is no need to build and examine the argument list.once(Goal) :- Goal, !.
once/1 can in many cases be replaced with ->/2. The only difference is how the cut behaves (see !/0). The following two clauses are identical:
1) a :- once((b, c)), d. 2) a :- b, c -> d.
ignore(Goal) :- Goal, !. ignore(_).
depth_limit_exceeded
if the limit was exceeded during the proof, or the entire predicate
fails if Goal fails without exceeding Limit.
The depth-limit is guarded by the internal machinery. This may differ from the depth computed based on a theoretical model. For example, true/0 is translated into an inlined virtual machine instruction. Also, repeat/0 is not implemented as below, but as a non-deterministic foreign predicate.
repeat. repeat :- repeat.
As a result, call_with_depth_limit/3 may still loop infinitely on programs that should theoretically finish in finite time. This problem can be cured by using Prolog equivalents to such built-in predicates.
This predicate may be used for theorem-provers to realise techniques like iterative deepening. It was implemented after discussion with Steve Moyle smoyle@ermine.ox.ac.uk.
Catcher is unified with a term describing how the call has finished. If this unification fails, Cleanup is not called.
!
Typical use of this predicate is cleanup of permanent data storage required to execute Goal, close file-descriptors, etc. The example below provides a non-deterministic search for a term in a file, closing the stream as needed.
term_in_file(Term, File) :- open(File, read, In), call_cleanup(term_in_stream(Term, In), _, close(In)). term_in_stream(Term, In) :- repeat, read(In, T), ( T == end_of_file -> !, fail ; T = Term ).
Note that this predicate is impossible to implement in Prolog other then reading all terms into a list, close the file and call member/2 because without call_cleanup/3 there is no way to gain control if the choice-point left by repeat is killed by a cut.
The call_cleanup/2 can also be used to test determinism of a goal, providing a portable alternative to deterministic/1:
?- call_cleanup((X=1;X=2), Det=yes). X = 1 ; X = 2, Det = yes ;
This predicate is a SWI-Prolog extension. See also call_cleanup/2 for compatibility to other Prolog implementations.
call_cleanup(Goal, _, Cleanup)
,
calling Cleanup regardless of the reason for termination and
without providing information. This predicate provides compatibility to
a number of other Prolog implementations.setup_and_call_cleanup(Setup, Goal, Cleanup) :- Setup, call_cleanup(Goal, Cleanup).