const reduce = (f, acc, iter) => {
if (!iter) {
iter = acc[Symbol.iterator]();
acc = iter.next().value;
}
for (const a of iter) {
log(a)
acc = f(acc, a);
}
return acc;
};
const go = (...args) => reduce((a, f) => f(a), args);
go(
0,
a => a + 1,
a => a + 10,
a => a + 100,
log)
// output
111
const pipe = (...fs) => (a) => go(a, ...fs);
const f = pipe(
(a, b) => a + b,
a => a + 10,
a => a + 100);
log(f(0, 1));
const log = console.log;
const curry = f =>
(a, ..._) => _.length ? f(a, ..._) : (..._) => f(a, ..._);
const mult = curry((a, b) => a * b);
log(mult(1))
log(mult(1,2))
log(mult(1)(2))
//output
(..._) => f(a, ..._)
2
2
const log = console.log;
const curry = f =>
(a, ..._) => _.length ? f(a, ..._) : (..._) => f(a, ..._);
const map = curry((f, iter) => {
let res = [];
for (const a of iter) {
res.push(f(a));
}
return res;
});
const filter = curry((f, iter) => {
let res = [];
for (const a of iter) {
if (f(a)) res.push(a);
}
return res;
});
const reduce = curry((f, acc, iter) => {
if (!iter) {
iter = acc[Symbol.iterator]();
acc = iter.next().value;
}
for (const a of iter) {
acc = f(acc, a);
}
return acc;
});
/* before */
go(
products,
products => filter(p => p.price < 20000, products),
products => map(p => p.price, products),
prices => reduce(add, prices),
log);
/* after */
go(
products,
filter(p => p.price < 20000),
map(p => p.price),
reduce(add),
log);
// output
30000
30000
두 코드의 평가 값이 같은 이유.
const reduce = curry((f, acc, iter) => { if (!iter) { iter = acc[Symbol.iterator](); acc = iter.next().value; } for (const a of iter) { acc = f(acc, a); log(a, acc) } return acc; });
- reduce의 for.. of문 안에 log를 찍어보면 첫 번째 경우는 사용자가 정의한 메서드 (filter, map, reduce)에 인자가 1개 이상으로 들어와 f(acc, a)에서 바로 결과가 나온다.
- 반면 두 번째 경우는 go 메서드 안에서 부터 filter, map, reduce에서 인자를 넘길 때 curry 함수를 호출한다. 이 때 1개의 인자만 받으므로 curry 메서드에서 f(a, ...) : (...)를 반환한다. 이 후 for .. of 문에서 다시 curry를 실행해 filter, map, reduce를 실행한다.'
const go = (...args) => reduce((a, f) => f(a), args);
const pipe = (f, ...fs) => (...as) => go(f(...as), ...fs);
const total_price = pipe(
map(p => p.price),
reduce(add));
const base_total_price = predi => pipe(
filter(predi),
total_price);
go(
products,
base_total_price(p => p.price < 20000),
log);
go(
products,
base_total_price(p => p.price >= 20000),
log);