Home Contents Index Summary Previous Next

3.7 Meta-Call Predicates

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(+Goal)
Invoke Goal as a goal. Note that clauses may have variables as subclauses, which is identical to call/1, except when the argument is bound to the cut. See !/0.

call(+Goal, +ExtraArg1, ...)
Append ExtraArg1, ExtraArg2, ... to the argument list of Goal and call the result. For example, 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(+Term, +List)
Append the members of List to the arguments of Term and call the resulting term. For example: 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.

not(+Goal)
Succeeds when Goal cannot be proven. Retained for compatibility only. New code should use \+/1.

once(+Goal)
Defined as: 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)
Calls Goal as once/1, but succeeds, regardless of whether Goal succeeded or not. Defined as:

ignore(Goal) :- Goal, !. ignore(_).

call_with_depth_limit(+Goal, +Limit, -Result)
If Goal can be proven without recursion deeper than Limit levels, call_with_depth_limit/3 succeeds, binding Result to the deepest recursion level used during the proof. Otherwise, Result is unified with 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 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 inifitly 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 iterrative deepening. It was implemented after discussion with Steve Moyle smoyle@ermine.ox.ac.uk.