|Did you know ...||Search Documentation:|
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.
read(Goal), call(Goal). Also a meta predicates such as ignore/1 are defined using call:
ignore(Goal) :- call(Goal), !. ignore(_).
ignore(Goal) :- Goal, !. ignore(_).
call(plus(1), 2, X)will call
plus(1, 2, X), binding X to 3.
The call/[2..] construct is handled by the compiler. The predicates call/[2-8] are defined as real (meta-)predicates and are available to inspection through current_predicate/1, predicate_property/2, etc.69Arities 2..8 are demanded by ISO/IEC 13211-1:1995/Cor.2:2012. Higher arities are handled by the compiler and runtime system, but the predicates are not accessible for inspection.70Future versions of the reflective predicate may fake the presence of call/9.. . Full logical behaviour, generating all these pseudo predicates, is probably undesirable and will become impossible if max_arity is removed.
apply(plus(1), [2, X])calls
plus(1, 2, X). New code should use call/[2..] if the length of List is fixed.
once(Goal) :- call(Goal), !.
can in many cases be replaced with ->/2.
The only difference is how the cut behaves (see !/0). The following two
clauses below are identical. Be careful about the interaction with
library defines an inline expansion of once/1,
mapping it to
(Goal->true;fail). Using the full
if-then-else constructs prevents its semantics from being changed when
embedded in a ;/2
1) a :- once((b, c)), d. 2) a :- b, c -> d.
ignore(Goal) :- Goal, !. ignore(_).
depth_limit_exceededif 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 inline 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. See also call_with_inference_limit/3. It was implemented after discussion with Steve Moyle email@example.com.
call(Goal), but limits the number of inferences for each solution of Goal.71This predicate was realised after discussion with Ulrich Neumerkel and Markus Triska.. Execution may terminate as follows:
inference_limit_exceededinto its execution. After termination of Goal, Result is unified with the atom
An inference is defined as a call or redo on a predicate. Please note that some primitive built-in predicates are compiled to virtual machine instructions for which inferences are not counted. The execution of predicates defined in other languages (e.g., C, C++) count as a single inference. This includes potentially expensive built-in predicates such as sort/2.
Calls to this predicate may be nested. An inner call that sets the limit below the current is honoured. An inner call that would terminate after the current limit does not change the effective limit. See also call_with_depth_limit/3 and call_with_time_limit/2.
(once(Setup), Goal). If Setup succeeds, Cleanup will be called exactly once after Goal is finished: either on failure, deterministic success, commit, or an exception. The execution of Setup is protected from asynchronous interrupts like call_with_time_limit/2 (package clib) or thread_signal/2. In most uses, Setup will perform temporary side-effects required by Goal that are finally undone by Cleanup.
Success or failure of Cleanup is ignored, and choice points it created are destroyed (as once/1). If Cleanup throws an exception, this is executed as normal while it was not triggered as the result of an exception the exception is propagated as normal. If Cleanup was triggered by an exception the rules are described in section 4.10.1
Typically, this predicate is used to cleanup 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) :- setup_call_cleanup(open(File, read, In), 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 it is impossible to implement this predicate in Prolog. The closest approximation would be to read all terms into a list, close the file and call member/2. Without setup_call_cleanup/3 there is no way to gain control if the choice point left by repeat/0 is removed by a cut or an exception.
?- setup_call_cleanup(true,(X=1;X=2), Det=yes). X = 1 ; X = 2, Det = yes ;
This predicate is under consideration for inclusion into the ISO standard. For compatibility with other Prolog implementations see call_cleanup/2.
setup_call_cleanup(Setup, Goal, Cleanup)with additional information on the reason for calling Cleanup. Prior to calling Cleanup, Catcher unifies with the termination code (see below). If this unification fails, Cleanup is not called.
?- setup_call_catcher_cleanup(true, (X=1;X=2), Catcher, writeln(Catcher)), throw(ball). external_exception(ball) ERROR: Unhandled exception: Unknown message: ball
setup_call_cleanup(true, Goal, Cleanup). This is provided for compatibility with a number of other Prolog implementations only. Do not use call_cleanup/2 if you perform side-effects prior to calling that will be undone by Cleanup. Instead, use setup_call_cleanup/3 with an appropriate first argument to perform those side-effects.
setup_call_catcher_cleanup(true, Goal, Catcher, Cleanup). The same warning as for call_cleanup/2 applies.