// map, filter는 지연성을 가진다. 중첩해서 사용하여 iterator를 만들어 가는 함수
// reduce는 시작점을 알리는 함수, iterator의 값들을 꺼내서 깨트리는 함수, 지연성을 가지기 보다는 연산이 이루어 진다.
// take는 몇개로 떨어질지 모르는 배열에서 특정 개수의 배열로 축약하고 완성을 지어버리는 함수, 지연성을 가지는 것 보다는 take한 시점에 연산이 이루어 진다.
// 예제) queryStr 함수
const queryStr = obj => go(
obj,
Object.entries,
map(([k, v]) => `${k}=${v}`),
reduce((a, b) => `${a}&{b}`)
);
console.log(queryStr({ limit: 10, offset: 10, type: 'notice' }));
// output : limit=10&offset=10&type=notice
// 예제) Array.prototype.join 보다 다형성 높은 join
const join = curry((sep=',', iter) => reduce((a, b) => `${a}${sep}${b}`, iter);
const queryStr = obj => go(
obj,
Object.entries,
map(([k, v]) => `${k}=${v}`),
join('&');
);
console.log(queryStr({ limit: 10, offset: 10, type: 'notice' }));
// output : limit=10&offset=10&type=notice
// 위에 코드와 달리 지연성을 가지는 join
L.entries = function *(obj) {
for (const k in obj) yield [k, obj[k]];
}
const queryStr = obj => pipe(
L.entries(obj),
L.map(([k, v]) => `${k}=${v}`),
join('&');
);
console.log(queryStr({ limit: 10, offset: 10, type: 'notice' }));
// 지연성을 가지는 join
// output : limit=10&offset=10&type=notice
const users = [
{ age: 32 },
{ age: 31 },
{ age: 37 },
{ age: 28 },
{ age: 25 },
{ age: 32 },
{ age: 31 },
{ age: 37 }
];
const find = curry((f, iter) => go(
iter,
L.filter(f), // find 함수에 지연성을 준다.
take(1),
([a]) => a
));
log(find(u => u.age < 30)(users));
go(users,
L.map(u => u.age),
find(n => n < 30),
console.log);
L.map = curry(function *(f, iter) {
for (const a of iter) {
yield f(a);
}
});
L.filter = curry(function *(f, iter) {
for (const a of iter) {
if(f(a)) yield a;
}
});
const takeAll = take(Infinity);
const map = curry(pipe(L.map, takeAll));
const filter = curry(pipe(L.filter, takeAll));
// 이런 값을 [[1, 2], 3, 4, [5, 6], [7, 8, 9]]
// [...[1, 2], 3, 4, ...[5, 6], ...[7, 8, 9]]
// 이렇게 동작하고 지연성을 가진다.
const isIterable = a => a && a[Symbol.iterator];
L.flatten = function *(iter) {
for (const a of iter) {
if(isIterable(a)) {
/*
for (const b of a)
yield b; */
yield *a
}
else yield a;
}
}
const it = L.flatten([...[1, 2], 3, 4, ...[5, 6], ...[7, 8, 9]])
console.log([...it])
// ---
const takeAll = take(Infinity)
const flatten = pipe(L.flatten, takeAll);
console.log(flatten([...[1, 2], 3, 4, ...[5, 6], ...[7, 8, 9]])
tip) yield *iterable = for (const val of iterable) yield val;
// 자바스크립트가 기본적으로 지연적을 동작하지 않기 때문에 만들어진 함수들
// 지연적으로 동작 하는 L.flatten 후 지연적인 동작을 하는 L.Map을 한 것이 L.flatMap
L.flatMap = curry(pipe(L.map, L.flatten));
const flatMap = curry(pipe(L.map, L.flatten, takeAll));
const it = L.flatMap(a => a, [[1, 2], [3, 4], [5, 6, 7]]
console.log([...it]);
console.log(L.flatMap(L.range, map(a => a + 1, [1, 2, 3]));
const arr = [
[1, 2],
[3, 4, 5],
[6, 7, 8],
[9, 10]
];
go(arr,
L.flatten,
L.filter(a => a % 2),
L.map(a => a * a),
take(3),
reduce(add),
console.log);
var users = [
{ name : 'a', age: 21, family: [
{ name: 'a1' age: 53 }, { name: 'a2', age: 47 }, { name: 'a3' age: 16 }, { name: 'a4', age: 15 }] },
{ name : 'b', age: 21, family: [
{ name: 'b1' age: 53 }, { name: 'b2', age: 47 }, { name: 'b3' age: 16 }, { name: 'b4', age: 15 }] },
{ name : 'c', age: 21, family: [
{ name: 'c1' age: 53 }, { name: 'c2', age: 47 }, { name: 'c3' age: 16 }, { name: 'c4', age: 15 }] },
{ name : 'd', age: 21, family: [
{ name: 'd1' age: 53 }, { name: 'd2', age: 47 }, { name: 'd3' age: 16 }, { name: 'd4', age: 15 }] }
];
go(users,
// L.map(u => u.family), // 가족을 뽑고
// L.flatten, // 가족을 펼치고
L.flatMap(u => u.family),
L.filter(u => u.age < 20), // 나이가 20 미만을 추출해서
L.map( u => u.name), // 이름만 가져온다.
take(4), // 4명의 이름만 가져온다.
console.log);