const reduce = curry((f, acc, iter) => {
if (!iter) {
iter = acc[Symbol.iterator]();
acc = iter.next().value;
} else {
iter = iter[Symbol.iterator]();
}
let cur;
while (!(cur = iter.next()).done) {
const a = cur.value;
acc = f(acc, a);
}
return acc;
});
const go = (...args) => reduce((a,f)=>f(a), args);
const curry = f => (a, ..._) => _.length ? f(a, ..._) : (..._) => f(a, ..._);
for of의 숨겨진 코드
const range = l => {
let i = -1;
let res = [];
while (++i < l) {
res.push(i);
}
return res;
};
const map = curry((f, iter) => {
let res = [];
iter = iter[Symbol.iterator]();
let cur;
while (!(cur = iter.next()).done) {
const a = cur.value;
res.push(f(a));
}
return res;
});
const filter = curry((f, iter) => {
let res = [];
iter = iter[Symbol.iterator]();
let cur;
while (!(cur = iter.next()).done) {
const a = cur.value;
if (f(a)) res.push(a);
}
return res;
});
const take = curry((l, iter) => {
let res = [];
iter = iter[Symbol.iterator]();
let cur;
while (!(cur = iter.next()).done) {
const a = cur.value;
res.push(a);
if (res.length == l) return res;
}
return res;
});
go(range(100000), map(n => n + 10), filter(n => n % 2), take(10), log);
const range = (l) => {
let res[];
let i = -1;
while(++i<l){
res.push(i);
}
return res;
}
const map = curry((f, iter)=>{
iter = iter[Symbol.lterator]();
let cur;
let res = [];
while(!(cur=iter.next()).done){
const a = cur.value;
res.push(f(a));
}
return res;
});
const filter = curry((f,iter)=>{
iter = iter[Symbol.lterator]();
let cur;
let res = [];
while(!(cur=iter.next()).done){
const a = cur.value;
if(a) res.push(a);
}
return res;
});
const take = curry((l, iter)=>{
iter = iter[Symbol.lterator]();
let cur;
let res = [];
while(!(cur=iter.next()).done){
const a = cur.value;
res.push(a);
if(res.length===l) return res;
}
return res;
});
let L = {};
L.range = funciton * (l) =>{
let i = -1;
while(++i<l){
yield i;
}
}
L.map = curry(funciton * (f, iter)=>{
iter = iter[Symbol.lterator]();
let cur;
while(!(cur=iter.next()).done){
const a = cur.value;
yield f(a);
}
});
L.map = curry(funciton * (f, iter)=>{
iter = iter[Symbol.lterator]();
let cur;
while(!(cur=iter.next()).done){
const a = cur.value;
if(a) yield a;
}
});
그에 반해서 지연실행 함수에서는
L.range = function* (l) {
let i = -1;
while (++i < l) {
yield i;
}
};
L.map = curry(function* (f, iter) {
iter = iter[Symbol.iterator]();
let cur;
while (!(cur = iter.next()).done) {
const a = cur.value;
yield f(a);
}
});
L.filter = curry(function* (f, iter) {
iter = iter[Symbol.iterator]();
let cur;
while (!(cur = iter.next()).done) {
const a = cur.value;
if (f(a)) {
yield a;
}
}
});
go(L.range(Infinity), L.map(n => n + 10), L.filter(n => n % 2), take(10), log);
코드를 실행하면 가장 먼저 take에 들어온다. 그 이유는 위에서부터 차례대로 제너레이터가 만든 이터레이터를 반환하기 때문이다. 이터네리이터는 바로 평가 되지 않고 지연 실행 되기 때문에 take부터 실행됨.
그래서 지연실행의 실행순서가 다르다.
지연실행 함수 = 제너레이터
지연 평가 : 메모리 효율성, 시간 효율성
다형성과 조합성
우선 1번 즉시 실행되는 함수
의 경우 한번에 배열을 다 만들고 하나씩 map, filter를 실행한후 take로 배열을 자른다.
그리고 2번의 경우 아래의 순서로 지연 실행
됩니다.
1. range가 제너레이터가 만든 이터레이터를 map에게 전달
2. map이 제너레이터가 만든 이터레이터를 filter에게 전달
3. filter는 제너레이터가 만든 이터레이터를 take에게 전달
- 여기서 이 이터레이터는 well-formed iterator이기 때문에 Symbol.iterator 매소드를 가집니다. 따라서 해당 코드는 아래 두가지 모두 가능하도록 다형성이 보장된 함수입니다.
- 이터러블 객체(=배열)
- 이터레이터(=제너레이터가 만든)
이렇든 즉시 평가 되는 함수와는 달리 제너레이터로 지연실행 시킨 함수
는 아래와 같은 장점을 가지고 있습니다.
그 중에서도 지연 평가의 장점은..?
1. 메모리 효율성 : 한꺼번에 처리하지 않고필요한 만큼 생성
하므로, 메모리 사용을 효율적으로 관리
2. 시간 효율성 : 복잡한 데이터 처리 작업을 수행할 때중간 결과
를 효율적으로 활용하고,필요한 시점에서만 계산을 수행
하여 시간을 절약