Explainer
Explainer including examples for the use of maplist/2 (and maplist/3 and maplist/4) here, including on using library(yall)
lambda expressions:
Examples for the Prolog predicate maplist∕2
...including on how to build the Goal.
If you have come here to look for "maps in Prolog", take a look at the Dict data structure
On the examples
Note the use of clumped/2 in the "Counting word frequency" example.
A predicate one needs again and again: Zipping/Unzipping a list
zip_unzip(Names,Values,Zipped) :- maplist([N,V,N-V]>>true,Names,Values,Zipped).
And thus:
?- zip_unzip([a,b,c,d],[alpha,bravo,charlie,delta],Z). Z = [a-alpha,b-bravo,c-charlie,d-delta]. ?- zip_unzip(N,V,[a-alpha,b-bravo,c-charlie,d-delta]). N = [a,b,c,d], V = [alpha,bravo,charlie,delta].
What if argument 2 is not a list?
If the List argument is not a list, then maplist fails instead of throwing.
?- maplist(atom,foo). false.
Prolog predicates are often too lenient, which is actually what is desired in a "logic setting" but may lead to hard-to-find errors.
Note that
forall/2 + member/2 is a replacement of maplist/2 (a not very useful observation; also forall/2 definitely rolls back any bindings made by the "verification" predicate)
Example:
?- forall(member(X,[a,b,c]),atomic(X)). true. ?- maplist(atomic,[a,b,c]). true. ?- forall(member(X,[a,f(b),c]),atomic(X)). false. ?- maplist(atomic,[a,f(b),c]). false.
Missed opportunity: Append to an open list
There should be a "maplist which appends to an open list" (i.e. it works with "a difference list of an open list"). Like this:
maplist_onto_open_list(_,[],FinalFin,FinalFin) :- !. maplist_onto_open_list(Goal,[In|MoreIn],[Out|Fin],FinalFin) :- call(Goal,In,Out), maplist_onto_open_list(Goal,MoreIn,Fin,FinalFin).
Then you can do:
test(Const,ListIn,ListOut,ListOutFinalFin) :- maplist_onto_open_list(prefix(Const),ListIn,ListOut,ListOutFinalFin). prefix(Const,StringIn,StringOut) :- atomic_list_concat([Const,StringIn],StringOut).
With output
?- test(foo,[a,b,c],L,Fin). L = [fooa,foob,fooc|Fin].
And this becomes useful if you want to chain operations that append to the same list
?- test(foo,[a,b,c],L,Fin1),test(bar,[a,b,c],Fin1,Fin2),test(baz,[a,b,c],Fin2,FinFin). L = [fooa,foob,fooc,bara,barb,barc,baza,bazb,bazc|FinFin], Fin1 = [bara,barb,barc,baza,bazb,bazc|FinFin], Fin2 = [baza,bazb,bazc|FinFin].