## 4.8 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.

[ISO]call(+Goal)
  Invoke Goal as a goal. Note that clauses may have variables as subclauses, which is identical to call/1.
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)
  True if Goal cannot be proven. Retained for compatibility only. New code should use \+/1.
[ISO]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 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.

call_cleanup(:Goal, +Catcher, :Cleanup)
  Calls Goal. If Goal is completely finished, either by deterministic success, failure, its choice-point being cut or raising an exception and Catcher unifies to the termination code (see below), Cleanup is called. Success or failure of Cleanup is ignored and possible choice-points it created are destroyed (as once/1). If Cleanup throws an exception this is executed as normal.bugDuring the execution of Cleanup, garbage collection and stack-shifts are disabled.

  Catcher is unified with a term describing how the call has finished. If this unification fails, Cleanup is not called.

  exit
    Goal succeeded without leaving any choice-points.
  fail
    Goal failed.
  `!`
    Goal succeeded with choice-points and these are now discarded by the execution of a cut (or other pruning of the search tree such as if-then-else).
  exception(Exception)
    Goal raised the given Exception.

  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) :-
              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 than by 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 removed 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 with other Prolog implementations.

call_cleanup(:Goal, :Cleanup)
  This predicate is equivalent to `call_cleanup(Goal, _, Cleanup)`, calling Cleanup regardless of the reason for termination and without providing information. This predicate provides compatibility with a number of other Prolog implementations.
setup_and_call_cleanup(:Setup, :Goal, :Cleanup)
  This predicate is introduced to allow for the proper definition of predicates with temporary side-effects under asynchronous interrupts from call_with_time_limit/2 (package clib) or thread_signal/2. It behaves as if defined below, but the Cleanup handler is also called if the interrupt occurs between Setup and the call_cleanup/2 call.

      setup_and_call_cleanup(Setup, Goal, Cleanup) :-
              Setup,
              call_cleanup(Goal, Cleanup).