Skip to content

Instantly share code, notes, and snippets.

@getify
Last active July 20, 2022 19:20
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save getify/2875f2e8bd74ced33b81afd6afaae599 to your computer and use it in GitHub Desktop.
Save getify/2875f2e8bd74ced33b81afd6afaae599 to your computer and use it in GitHub Desktop.
transducing even with reducers
var filterReducer = pf => cf => (acc,v) => pf(v) ? cf(acc,v) : acc;
var mapReducer = mf => cf => (acc,v) => cf(acc,mf(v));
var compose = (...fs) => v => fs.reduceRight((r,f) => f(r),v);
var concat = (acc,v) => [ ...acc, v ];
var sum = (x,y) => x + y;
// ************************************
var onlyOdds = v => v % 2 == 1;
var double = v => v * 2;
var onlyHundreds = cf => (vs,v) => v % 10 == 0 ? cf(vs,v * 10) : vs;
// ************************************
var list = [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 20 ];
// ************************************
// OPTION 1 (no transducing)
list
.filter(onlyOdds)
.map(double)
.reduce(onlyHundreds(concat),[]);
// [ 100, 300 ]
list
.filter(onlyOdds)
.map(double)
.reduce(onlyHundreds(sum),0);
// 400
var filterReducer = pf => cf => (acc,v) => pf(v) ? cf(acc,v) : acc;
var mapReducer = mf => cf => (acc,v) => cf(acc,mf(v));
var compose = (...fs) => v => fs.reduceRight((r,f) => f(r),v);
var concat = (acc,v) => [ ...acc, v ];
var sum = (x,y) => x + y;
// ************************************
var onlyOdds = v => v % 2 == 1;
var double = v => v * 2;
var onlyHundreds = cf => (vs,v) => v % 10 == 0 ? cf(vs,v * 10) : vs;
// ************************************
var list = [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 20 ];
// ************************************
// OPTION 2 (transducing but without including the onlyHundreds(..) reducer)
list
.reduce(
compose(
filterReducer(onlyOdds),
mapReducer(double)
)(concat),
[]
)
.reduce(onlyHundreds(concat),[]);
// [ 100, 300 ]
list
.reduce(
compose(
filterReducer(onlyOdds),
mapReducer(double)
)(concat),
[]
)
.reduce(onlyHundreds(sum),0);
// 400
var filterReducer = pf => cf => (acc,v) => pf(v) ? cf(acc,v) : acc;
var mapReducer = mf => cf => (acc,v) => cf(acc,mf(v));
var compose = (...fs) => v => fs.reduceRight((r,f) => f(r),v);
var concat = (acc,v) => [ ...acc, v ];
var sum = (x,y) => x + y;
// ************************************
var onlyOdds = v => v % 2 == 1;
var double = v => v * 2;
var onlyHundreds = cf => (vs,v) => v % 10 == 0 ? cf(vs,v * 10) : vs;
// ************************************
var list = [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 20 ];
// ************************************
// OPTION 3 (transducing EVEN INCLUDING the onlyHundreds(..) reducer)
// **this** is the crazy new invention, an adapter that makes reducers composable
// as transducers, similar to how mapReducer(..) and filterReducer(..) do so for
// maps and filters, respectively.
var reduceReducer = (rf,diff,eq) => cf => (acc,v) => {
var res = rf(acc,v);
if (!eq(acc,res)) {
return cf(acc,diff(acc,res));
}
else {
return acc;
}
};
var listDiff = (vs,ws) => ws[ws.length - 1];
var listEq = (vs,ws) => {
if (vs.length != ws.length) return false;
return (vs[vs.length - 1] === ws[ws.length - 1]);
};
var numDiff = (x,y) => y - x;
var numEq = (x,y) => x === y;
list
.reduce(
compose(
filterReducer(onlyOdds),
mapReducer(double),
reduceReducer(onlyHundreds(concat),listDiff,listEq)
)(concat),
[]
);
// [ 100, 300 ]
list
.reduce(
compose(
filterReducer(onlyOdds),
mapReducer(double),
reduceReducer(onlyHundreds(sum),numDiff,numEq)
)(sum),
0
);
// 400
var compose = (...fs) => v => fs.reduceRight((r,f) => f(r),v);
var concat = (acc,v) => [ ...acc, v ];
var sum = (x,y) => x + y;
// ************************************
var onlyOdds = v => v % 2 == 1;
var double = v => v * 2;
// ************************************
var list = [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 20 ];
// ************************************
// OPTION 4 (transducing by composing ONLY reducers!)
// **this** is the crazy new invention, an adapter that makes reducers composable
// as transducers, similar to how mapReducer(..) and filterReducer(..) do so for
// maps and filters, respectively.
var reduceReducer = (rf,diff,eq) => cf => (acc,v) => {
var res = rf(acc,v);
if (!eq(acc,res)) {
return cf(acc,diff(acc,res));
}
else {
return acc;
}
};
var listDiff = (vs,ws) => ws[ws.length - 1];
var listEq = (vs,ws) => {
if (vs.length != ws.length) return false;
return (vs[vs.length - 1] === ws[ws.length - 1]);
};
var numDiff = (x,y) => y - x;
var numEq = (x,y) => x === y;
list
.reduce(
compose(
reduceReducer((acc,v) => onlyOdds(v) ? [ ...acc, v ] : acc,listDiff,listEq),
reduceReducer((acc,v) => [ ...acc, double(v) ],listDiff,listEq),
reduceReducer((acc,v) => v % 10 == 0 ? [ ...acc, v * 10 ] : acc,listDiff,listEq)
)(concat),
[]
);
// [ 100, 300 ]
list
.reduce(
compose(
reduceReducer((acc,v) => onlyOdds(v) ? acc + v : acc,numDiff,numEq),
reduceReducer((acc,v) => acc + double(v),numDiff,numEq),
reduceReducer((acc,v) => v % 10 == 0 ? acc + (v * 10) : acc,numDiff,numEq)
)(sum),
0
);
// 400
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment