코드스피츠73 part4
ABSTRACT LOOP & LAZY EXECUTION
단순한 루프
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| { [Symbol.iterator](){return this;}, data : [1,2,3,4], next() { return { done : this.data.length === 0, value : this.data.shift() }; } }
|
복잡한 루프
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| { [Symbol.iterator](){return this;}, data : [{a:[1,2,3,4], b:'-'},[5,6,7],8,9], next() { let v; while (v = this.data.shift()){ switch (true){ case Array.isArray(v):{ this.data.unshift(...v); break; } case v && typeof v == 'object':{ for(let k in v) this.data.unshift(v[k]); break; } default : return {value: v, done:false} } } return {done:true} } }
|
ABSTRACT LOOP
다양한 구조의 루프와 무관하게 해당 값이나 상황만 개입만 하고 싶은경우
1 2 3 4 5 6 7 8 9 10 11
| (data, f) => { let v; while (v = data.shift()){ if(!(v instanceof Object)) f(v); else { if(!Array.isArray(v)) v = Object.values(v); data.unshift(...v); } } }
|
위에 함수에서 console.log 만 추가 할려고 해도 아래 처럼 수정 할수 밖에 없다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| (data, f) => { let v; while (v = data.shift()){ if(!(v instanceof Object)){ console.log(v); f(v); } else { if(!Array.isArray(v)) v = Object.values(v); data.unshift(...v); } } }
|
코드는 고정 되어 있고 변수가 상태를 바꾼다.
위에 함수를 객체화로 바꾸면 아래 처럼 된다.
팩토리 + 컴포지트
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| const Operator = class{ static factory(v){ if(v instanceof Object){ if(!Array.isArray(v)) v = Object.values(v); return new ArrayOp(v.map(v=> Operator.factory(v))); }else{ return new PrimaOp(v); } } constructor(v){ this.v = v; } operation(f){throw 'override';} };
const PrimaOp = class extends Operator{ constructor(v){ this.v = v; } operation(f){ f(this.v); } };
const ArrayOp class extends Operator{ constructor(v){ this.v = v; } operation(f){ for(const v of this.v){ v.operation(f); } } };
Operator.factory([1,2,3,{a:4,b:5},6,7]).operation(console.log);
|
팩토리 + 컴포지트 + ES6 Iterable
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
|
const Operator = class{ static factory(v){ if(v instanceof Object){ if(!Array.isArray(v)) v = Object.values(v); return new ArrayOp(v.map(v=> Operator.factory(v))); }else{ return new PrimaOp(v); } } constructor(v){ this.v = v; } *gene(){throw 'override';} };
const PrimaOp = class extends Operator{ constructor(v){ this.v = v; } *gene(){ yield this.v; } };
const ArrayOp class extends Operator{ constructor(v){ this.v = v; } *gene(){ for(const v of this.v){ yield * v.gene() } } };
for(const v of Operator.factory([1,2,3,{a:4,b:5},6,7]).gene()) console.log(v);
|
LAZY EXECUTION
YIELD
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| const odd = function*(data) { for (const v of data){ console.log('odd',odd.cnt ++); if(v % 2) yield v; } };
odd.cnt =0; for(const v of odd([1,2,3,4])) console.log(v);
const take= function*(data, n) { for (const v of data){ console.log('take',take.cnt ++); if(n--) yield v; else break; } };
take.cnt =0; for(const v of take([1,2,3,4], 2)) console.log(v);
for(const v of take(odd([1,2,3,4]), 2)) console.log(v);
|
YIELD*
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| const Stream = class{ static get(v){return new Stream(v);} constructor(v){ this.v = v; this.filters = []; } add(gene, ...arg){ this.filters.push(v=>gene(v, ...arg)); return this; } *gene(){ let v = this.v; for(const f of this.filters) v = f(v); yield* v; } };
const odd = function*(data){ for(const v of data) if(v % 2) yield v; };
const take = function*(data, n){ for(const v of data) if(n--) yield v; else break; };
for(const v of Stream.get([1,2,3,4]).add(odd).add(take, 2).gene()) console.log(v);
|
어렵네요… ㅜㅜ
참조