HiveBrain v1.2.0
Get Started
← Back to all entries
patternMinor

map + foldl = mapfoldl

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
mapmapfoldlfoldl

Problem

I was wondering... In the standard library of some Prolog systems, there are meta-predicates like maplist and foldl.

In general, when using meta-predicates (like the ones above) with dcg we always need the "foldl" variants. What about the following mapfoldl/5 (mapfoldl//3)?

mapfoldl(P_4,Xs,Zs,S0,S) :-
   list_mapfoldl_(Xs,Zs,S0,S,P_4).

list_mapfoldl_([],[],S,S,_).
list_mapfoldl_([X|Xs],[Y|Ys],S0,S,P_4) :-
   call(P_4,X,Y,S0,S1),
   list_mapfoldl_(Xs,Ys,S1,S,P_4).


What's your take on this code? They isn't this (or something very similar) already in the stdlibs?

Solution

In the Logtalk library, you have a map_reduce/5 predicate:

:- public(map_reduce/5).
:- meta_predicate(map_reduce(2, 3, *, *, *)).
:- mode(map_reduce(+callable, +callable, +term, ?list, ?term), zero_or_more).
:- info(map/5, [
    comment is 'Map a list and apply a fold left (reduce) to the resulting list.',
    argnames is ['Map', 'Reduce', 'Accumulator', 'List', 'Result']
]).

map_reduce(Map, Reduce, Acc, List, Result) :-
    map_reduce_(List, Map, Reduce, Acc, Result).

:- meta_predicate(map_reduce_(*, 2, 3, *, *)).
map_reduce_([], _, _, Result, Result).
map_reduce_([Arg| Args], Map, Reduce, Acc, Result) :-
    call(Map, Arg, Arg2),
    call(Reduce, Acc, Arg2, Acc2),
    map_reduce_(Args, Map, Reduce, Acc2, Result).


A main difference to your code is that you assume a single closure combining both the map and reduce operations in the Logtalk version. You also return the map result in addition to the final fold result.

Code Snippets

:- public(map_reduce/5).
:- meta_predicate(map_reduce(2, 3, *, *, *)).
:- mode(map_reduce(+callable, +callable, +term, ?list, ?term), zero_or_more).
:- info(map/5, [
    comment is 'Map a list and apply a fold left (reduce) to the resulting list.',
    argnames is ['Map', 'Reduce', 'Accumulator', 'List', 'Result']
]).

map_reduce(Map, Reduce, Acc, List, Result) :-
    map_reduce_(List, Map, Reduce, Acc, Result).

:- meta_predicate(map_reduce_(*, 2, 3, *, *)).
map_reduce_([], _, _, Result, Result).
map_reduce_([Arg| Args], Map, Reduce, Acc, Result) :-
    call(Map, Arg, Arg2),
    call(Reduce, Acc, Arg2, Acc2),
    map_reduce_(Args, Map, Reduce, Acc2, Result).

Context

StackExchange Code Review Q#91248, answer score: 3

Revisions (0)

No revisions yet.