Goals as Data: The Foundation of Higher-Order Prolog
Because a Prolog goal is just an ordinary term until it is executed, predicates can accept goals as arguments and invoke them later, giving the language a natural style of higher-order programming without any special syntax for functions-as-values. This is the mechanism behind library(apply) predicates like maplist/2..5 and foldl/4..6, and behind library(yall)'s lambda expressions, all of which let you parameterize control flow — 'do this for every element' or 'combine these into one value' — by a predicate supplied at the call site rather than hard-coded into the traversal logic.
Cricket analogy: It's like a captain who can hand any bowler the ball and trust the same 'bowl an over' routine to work regardless of who's holding it — a Prolog goal is just a term you can pass around and invoke later, the way any bowler slots into the same over-management routine.
call/N and Partial Application
call(Goal, Arg1, ..., ArgN) constructs a new goal by appending the extra arguments to Goal's existing arguments and then calls the result — so call(plus(1), 2, X) calls plus(1, 2, X), unifying X with 3. This lets a predicate like greater_than(5) act as a partially-applied comparison that maplist/3 or include/3 can later supply the missing argument to, which is how Prolog achieves something close to closures despite lacking first-class function syntax.
Cricket analogy: It's like a fielding coach saying 'catching drill' and letting the specific fielder's name be filled in later when the drill actually runs — call(catching_drill, Fielder) appends the missing argument at call time, just as plus(1) waits for its second number to complete the addition.
maplist/[2-5]: Mapping Across Lists
maplist(Goal, List1) calls Goal on every element of List1, failing if any call fails; the family extends to maplist/3, /4, and /5, which walk two, three, or four lists in lockstep, calling Goal with one element from each list at every step — so maplist(writeln, [a,b,c]) prints three lines, while maplist(plus(1), [1,2,3], Sums) computes Sums = [2,3,4] by pairing each input list element with the corresponding output. All the lists involved must be the same length, or the shorter one determines how many times Goal is called and the rest fail to unify.
Cricket analogy: It's like a fielding coach running the exact same catching drill on every player in the squad one after another — maplist(Goal, Players) applies one routine uniformly to every element, while maplist/3 pairs each player with a specific target catch count from a second list simultaneously.
?- maplist(writeln, [red, green, blue]).
red
green
blue
?- maplist([X,Y]>>(Y is X*X), [1,2,3,4], Squares).
Squares = [1, 4, 9, 16].
?- foldl([X,A0,A]>>(A is A0+X), [1,2,3,4,5], 0, Sum).
Sum = 15.
?- include([X]>>(X mod 2 =:= 0), [1,2,3,4,5,6], Evens).
Evens = [2, 4, 6].
?- partition([X]>>(X > 3), [1,5,2,8,3], Big, Small).
Big = [5, 8], Small = [1, 2, 3].foldl/4, include/3, exclude/3, and partition/4
foldl(Goal, List, V0, V) threads an accumulator through the list, calling Goal(Elem, AccIn, AccOut) at each step so that the final AccOut becomes V — it is how you express sum, product, or any left-to-right reduction without writing an explicit recursive helper predicate. include(Goal, List, Included) and exclude(Goal, List, Excluded) filter a list by keeping or dropping elements for which Goal succeeds, while partition(Goal, List, Included, Excluded) does both passes in one traversal, splitting List into the elements that satisfy Goal and those that don't.
Cricket analogy: It's like a scorer running total-runs through an over ball by ball, carrying the running total from delivery to delivery — foldl mirrors this threading of an accumulator, while include/exclude are like separately filtering deliveries into 'boundaries' and 'dot balls' lists.
SWI-Prolog's library(yall) supplies the [Params]>>Goal lambda syntax used throughout these examples (e.g., [X,Y]>>(Y is X*X)); without it you must define a named auxiliary predicate for every one-off transformation passed to maplist/foldl, which is considerably more verbose for small, throwaway operations.
- A Prolog goal is an ordinary term until executed, which lets predicates accept and later call goals supplied as arguments.
- call(Goal, Arg1, ..., ArgN) appends extra arguments to Goal and calls the result, enabling partial application.
- maplist/2..5 applies a goal to corresponding elements across one to four lists in lockstep.
- foldl/4 threads an accumulator through a list left-to-right, expressing reductions without a hand-written recursive helper.
- include/3 and exclude/3 filter a list by keeping or dropping elements for which a goal succeeds.
- partition/4 splits a list into two lists in a single traversal based on a goal's success or failure.
- library(yall) lambda syntax ([Params]>>Goal) avoids defining a named auxiliary predicate for small one-off transformations.
Practice what you learned
1. What does call(plus(1), 2, X) evaluate to?
2. What does maplist(plus(1), [1,2,3], Sums) bind Sums to?
3. What is the role of the accumulator arguments in foldl(Goal, List, V0, V)?
4. How does partition/4 differ from calling include/3 and exclude/3 separately?
5. What does library(yall)'s [X]>>Goal syntax provide?
Was this page helpful?
You May Also Like
findall, bagof, and setof
The three built-in all-solutions predicates that collect every proof of a goal into a list, each with different rules for failure, grouping, and duplicates.
assert and retract
How Prolog programs modify their own clause database at runtime using assert, asserta, assertz, retract, and retractall.
Constraint Logic Programming
How CLP(FD) extends Prolog with propagating constraints over finite domains, replacing brute-force generate-and-test with early pruning.
Related Reading
Related Study Notes in Programming
Browse all study notesApache Spark Study Notes
Programming · 30 topics
ProgrammingApache Flink Study Notes
Programming · 30 topics
ProgrammingHadoop Study Notes
Programming · 30 topics
ProgrammingSnowflake Study Notes
Programming · 30 topics
ProgrammingApache Airflow Study Notes
Programming · 30 topics
Programmingdbt (Data Build Tool) Study Notes
Programming · 30 topics