Higher-Order & Meta Predicates

Variables in lambda bodies are copied unless declared free with \ or / — a frequent gotcha; or define a helper predicate instead.

22.1 call/N

?- G = format("~w~n", [hi]), call(G).
?- P = succ, call(P, 3, X).          % X = 4
twice(G, X, Z) :- call(G, X, Y), call(G, Y, Z).
?- twice(succ, 1, R).                % R = 3

22.2 library(apply)

?- maplist(succ, [1, 2, 3], L).                    % L = [2, 3, 4]
?- maplist([X, Y]>>(Y is X * X), [1, 2, 3], L).    % yall lambda: L = [1, 4, 9]
?- maplist(=(0), L), length(L, 3).                 % L = [0, 0, 0]
?- maplist([X]>>(X > 0), [1, 2]).                  % check all
?- maplist([X, Y, Z]>>(Z is X + Y), [1, 2], [10, 20], S).   % zipWith: S = [11, 22]
?- include([X]>>(X mod 2 =:= 0), [1, 2, 3, 4], E). % E = [2, 4]
?- exclude([X]>>(X > 2), [1, 2, 3], R).            % R = [1, 2]
?- partition([X]>>(X < 3), [1, 5, 2, 4], In, Out).
?- foldl([X, A0, A]>>(A is A0 + X), [1, 2, 3], 0, Sum).   % Sum = 6
?- aggregate_all(count, member(_, [a, b]), N).

22.3 Lambdas: library(yall)

Variables in lambda bodies are copied unless declared free with \ or / — a frequent gotcha; or define a helper predicate instead.

[X]>>Goal                    % parameters
\X^Goal                      % lambda with local variable
/(Free, [X]>>Goal)           % Free variables shared with context: Free/[X]>>Goal
add_n(N, L0, L) :- maplist([X, Y]>>(Y is X + N), L0, L).   % N is captured (copy semantics apply!)

22.4 Meta-predicate declarations

The number tells how many extra arguments are added; : means module-sensitive; ^ for bagof-style; // for DCG bodies. Needed so goals are resolved in the caller's module.

:- meta_predicate apply_twice(1, ?).
apply_twice(G, X) :- call(G, X), call(G, X).

22.5 Goals as data

run_all([]).
run_all([G|Gs]) :- call(G), run_all(Gs).
?- run_all([X = 1, Y is X + 1, writeln(Y)]).