Reading — step 1 of 4
Learn
~2 min readDCG, CLP, Meta-Programming
Prolog code IS data. Programs can construct, inspect, and execute terms — making meta-programming easy.
call/N
The most common meta-call. call(Goal) runs Goal as if it were called directly:
?- G = write(hello), call(G).
hello
G = write(hello).
?- call(write, hello). %% same — multi-arity call
hello
With extra args, call/N adds them: call(Pred, Arg1, Arg2) is Pred(Arg1, Arg2).
Higher-order patterns
%% maplist applies a goal to each list element
?- maplist(succ, [1, 2, 3], L).
L = [2, 3, 4].
?- maplist([X, Y]>>(Y is X * 2), [1, 2, 3], L).
L = [2, 4, 6]. %% lambda-like syntax
%% Filter
?- include([X]>>(X > 5), [1, 5, 10, 15], L).
L = [10, 15].
%% Fold
?- foldl([X, Acc, NewAcc]>>(NewAcc is Acc + X), [1,2,3,4,5], 0, S).
S = 15.
Inspecting terms
?- functor(foo(a, b, c), Name, Arity).
Name = foo, Arity = 3.
?- arg(2, foo(a, b, c), Arg).
Arg = b.
?- T =.. [foo, a, b, c]. %% "univ" — convert to/from list
T = foo(a, b, c).
?- foo(a, b, c) =.. L.
L = [foo, a, b, c].
Building goals at runtime
run_op(Op, X, Y, R) :-
Goal =.. [Op, X, Y, R],
call(Goal).
?- run_op(plus, 3, 4, R).
R = 7.
This builds the goal plus(3, 4, R) from parts and calls it.
assert for code generation
:- dynamic(square/2).
build_squares(N) :-
forall(between(1, N, X),
( Sq is X * X,
assertz(square(X, Sq))
)).
?- build_squares(5).
?- square(3, S).
S = 9.
Generated facts at runtime — useful for caching, derived data, dynamic rule sets.
apply style
:- use_module(library(yall)). %% SWI lambda library
transform(Pred, [X|T], [Y|TT]) :-
call(Pred, X, Y),
transform(Pred, T, TT).
transform(_, [], []).
?- transform([X, Y]>>(Y is X * 2), [1, 2, 3], R).
R = [2, 4, 6].
clause/2 for introspection
?- clause(member(X, [1, 2, 3]), Body).
%% returns the body of one matching clause
Useful for debuggers, profilers, theorem provers.
Practical use
- Generic predicates — work with any predicate via
call/N - DSL implementation — meta-interpret a custom language
- Theorem provers — manipulate logic formulas as terms
- Code analysis — walk and rewrite source clauses
Prolog's homoiconic nature (code = data) plus unification = a metaprogramming sweet spot.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…