PLOGHELP CALL Simon Nichols, April 1992 A family of predicates for calling terms as goals. ?- call(G). ?- call(P, Arg1, ..., ArgN). If G is instantiated to a term which would be acceptable as a goal in the body of a clause, i.e., an atom or compound term, the goal call(G) is executed exactly as if that term appeared textually in its place, except that any cut (!) occurring in G only cuts alternatives in the execution of G (in other words, it does not affect the clause which contains the goal call(G)). If G is not instantiated to an atom or compound term, call/1 raises an error. In particular, if G is unbound an instantiation fault is raised. The predicate call/1 is used by a program which needs to construct a goal as it runs and then execute that goal. Poplog Prolog allows the variable G to be used on its own as a goal, i.e., G and call(G) are equivalent. For compatibility with DEC-10 Prolog, incore/1 is accepted as a synonym for call/1. As an example, the following are all equivalent: ?- write(hello). ?- Goal = write(hello), call(Goal). ?- Goal = write(hello), Goal. ?- Goal = write(hello), incore(Goal). There are potential efficiency penalties to using call/1. These result from the need to build a term out of a predicate and its arguments before it can be called as a goal. Consider the predicate maplist/3: % maplist(+Pred, +Xs, ?Ys) % is true when Pred(X, Y) is true for each X in Xs and Y in Ys. maplist(P, [], []). maplist(P, [X|Xs], [Y|Ys]) :- P =.. L0, append(L0, [X,Y], L), G =.. L, call(G), maplist(P, Xs, Ys). This is a very useful predicate, but is expensive (in time and memory use) due to the calls to =../2 ("univ") and append/3. The call to append/3 might appear to be unnecessary. However, P might not be an atom (bound to the functor name of a two argument predicate) but a term, representing a "closure", i.e., a predicate with some "frozen" arguments. In that case, X and Y would have to be added to the end of any frozen arguments from the closure. For this reason, Poplog Prolog provides a whole family of call predicates, the call/N family (for any arity N > 0). In general, call/N applies it first argument, either a predicate or closure, to its remaining N-1 arguments. Moreover, it does so efficiently, without any additional data structures being created, and quickly. In fact, the overhead involved in using call/N is almost negligible. This makes the definition and use of higher-order predicates such as maplist/3 perfectly practical in a production environment. Using call/3, maplist/3 may be defined as: maplist(P, [], []). maplist(P, [X|Xs], [Y|Ys]) :- call(P, X, Y), maplist(P, Xs, Ys). Indeed, it is so defined in library(higher_order). See PLOGHELP * HIGHER_ORDER. In principle, call/3 could be defined using call/1 as follows: call(P, X, Y) :- P =.. L, append(L, [X, Y], L1), G =.. L1, call(G). Though this has the same meaning as the built-in call/3, the built-in version is far more efficient. --- C.all/plog/help/call --- Copyright University of Sussex 1992. All rights reserved. ----------