코드스피츠73 part4

ABSTRACT LOOP & LAZY EXECUTION

단순한 루프


{
    [Symbol.iterator](){return this;},
    data : [1,2,3,4],
    next() {
        return {
            //계속 반복할지 판단 
            done : this.data.length === 0,
            //반복시마다 처리할 것
            value : this.data.shift()
           
        };
    }
}

복잡한 루프


{
    [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

다양한 구조의 루프와 무관하게 해당 값이나 상황만 개입만 하고 싶은경우

(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 만 추가 할려고 해도 아래 처럼 수정 할수 밖에 없다.


(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);
        }
    }
}

코드는 고정 되어 있고 변수가 상태를 바꾼다. 위에 함수를 객체화로 바꾸면 아래 처럼 된다.

팩토리 + 컴포지트


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



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


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*


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);

어렵네요… ㅜㅜ

참조