반볡자(Iterators)

반볡자 μžμ²΄λŠ” TypeScript λ˜λŠ” ES6 κΈ°λŠ₯은 μ•„λ‹™λ‹ˆλ‹€. λ°˜λ³΅μžλŠ” 객체 지ν–₯ ν”„λ‘œκ·Έλž˜λ° μ–Έμ–΄λ₯Ό μœ„ν•œ 행동 λ””μžμΈ νŒ¨ν„΄μž…λ‹ˆλ‹€. 일반적으둜 λ‹€μŒ μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•˜λŠ” κ°μ²΄μž…λ‹ˆλ‹€.

interface Iterator<T> {
    next(value?: any): IteratorResult<T>;
    return?(value?: any): IteratorResult<T>;
    throw?(e?: any): IteratorResult<T>;
}

이 μΈν„°νŽ˜μ΄μŠ€λŠ” 객체에 μ†ν•œ 집합 λ˜λŠ” μ‹œν€€μŠ€(sequence)μ—μ„œ 값을 κ°€μ Έμ˜¬ 수 μžˆμŠ΅λ‹ˆλ‹€.

IteratorResultλŠ” λ‹¨μˆœνžˆ value+done μŒμž…λ‹ˆλ‹€.:

interface IteratorResult<T> {
    done: boolean;
    value: T;
}

μ–΄λ–€ Frame을 κ΅¬μ„±ν•˜λŠ” Component λͺ©λ‘μ„ ν¬ν•¨ν•˜λŠ” Frame의 객체가 μžˆλ‹€κ³  μƒμƒν•˜μ„Έμš”. λ‹€μŒκ³Ό 같이 반볡자 μΈν„°νŽ˜μ΄μŠ€λ‘œ 이 Frame κ°μ²΄μ—μ„œ Componentλ₯Ό κ°€μ Έμ˜¬ 수 μžˆμŠ΅λ‹ˆλ‹€.:

class Component {
  constructor (public name: string) {}
}

class Frame implements Iterator<Component> {

  private pointer = 0;

  constructor(public name: string, public components: Component[]) {}

  public next(): IteratorResult<Component> {
    if (this.pointer < this.components.length) {
      return {
        done: false,
        value: this.components[this.pointer++]
      }
    } else {
      return {
        done: true
      }
    }
  }

}

let frame = new Frame("Door", [new Component("top"), new Component("bottom"), new Component("left"), new Component("right")]);
let iteratorResult1 = frame.next(); //{ done: false, value: Component { name: 'top' } }
let iteratorResult2 = frame.next(); //{ done: false, value: Component { name: 'bottom' } }
let iteratorResult3 = frame.next(); //{ done: false, value: Component { name: 'left' } }
let iteratorResult4 = frame.next(); //{ done: false, value: Component { name: 'right' } }
let iteratorResult5 = frame.next(); //{ done: true }

//It is possible to access the value of iterator result via the value property:
let component = iteratorResult1.value; //Component { name: 'top' }

λ°˜λ³΅ν•˜λ©΄ 반볡자 μžμ²΄λŠ” TypeScript κΈ°λŠ₯이 μ•„λ‹™λ‹ˆλ‹€. 이 μ½”λ“œλŠ” Iterator와 IteratorResult μΈν„°νŽ˜μ΄μŠ€λ₯Ό λͺ…식적인 κ΅¬ν˜„ 없이도 잘 λ™μž‘ν•  κ²ƒμž…λ‹ˆλ‹€. κ·ΈλŸ¬λ‚˜ μ½”λ“œ 일관성을 μœ„ν•΄ 곡톡 ES6 interfacesλ₯Ό μ‚¬μš©ν•˜λŠ” 것이 맀우 μœ μš©ν•©λ‹ˆλ‹€.

λ„€ μ’‹μŠ΅λ‹ˆλ‹€. 더 μœ μš©ν•  κ²ƒμž…λ‹ˆλ‹€. ES6λŠ” Iterable μΈν„°νŽ˜μ΄μŠ€κ°€ κ΅¬ν˜„λ˜λ©΄ [Symbol.iterator] symbol을 ν¬ν•¨ν•˜λŠ” iteratable protocol을 μ •μ˜ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€.

//...
class Frame implements Iterable<Component> {

  constructor(public name: string, public components: Component[]) {}

  [Symbol.iterator]() {
    let pointer = 0;
    let components = this.components;

    return {
      next(): IteratorResult<Component> {
        if (pointer < components.length) {
          return {
            done: false,
            value: components[pointer++]
          }
        } else {
          return {
            done: true,
            value: null
          }
        }
      }
    }
  }
}

let frame = new Frame("Door", [new Component("top"), new Component("bottom"), new Component("left"), new Component("right")]);
for (let cmp of frame) {
  console.log(cmp);
}

λΆˆν–‰ν•˜κ²Œλ„ 이 νŒ¨ν„΄μ—μ„œλŠ” frame.next()λŠ” λ™μž‘ν•˜μ§€ μ•Šμ„ 것이고 λ‹€μ†Œ κ±°μΆ”μž₯슀럽게 보일 κ²ƒμž…λ‹ˆλ‹€. ꡬ쑰λ₯Ό μœ„ν•΄ IterableIterator μΈν„°νŽ˜μ΄μŠ€λ₯Ό!

//...
class Frame implements IterableIterator<Component> {

  private pointer = 0;

  constructor(public name: string, public components: Component[]) {}

  public next(): IteratorResult<Component> {
    if (this.pointer < this.components.length) {
      return {
        done: false,
        value: this.components[this.pointer++]
      }
    } else {
      return {
        done: true,
        value: null
      }
    }
  }

  [Symbol.iterator](): IterableIterator<Component> {
    return this;
  }

}
//...

IterableIterator μΈν„°νŽ˜μ΄μŠ€λ‘œ frame.next()와 for μˆœν™˜ λͺ¨λ‘ 잘 λ™μž‘ν•©λ‹ˆλ‹€.

λ°˜λ³΅μžλŠ” μœ ν•œν•œ 값을 λ°˜λ³΅ν•  ν•„μš”λŠ” μ—†μŠ΅λ‹ˆλ‹€. μ „ν˜•μ μΈ μ˜ˆκ°€ ν”Όλ³΄λ‚˜μΉ˜ μˆ˜μ—΄μž…λ‹ˆλ‹€.:

class Fib implements IterableIterator<number> {

  protected fn1 = 0;
  protected fn2 = 1;

  constructor(protected maxValue?: number) {}

  public next(): IteratorResult<number> {
    var current = this.fn1;
    this.fn1 = this.fn2;
    this.fn2 = current + this.fn1;
    if (this.maxValue != null && current >= this.maxValue) {
      return {
        done: true,
        value: null
      } 
    } 
    return {
      done: false,
      value: current
    }
  }

  [Symbol.iterator](): IterableIterator<number> {
    return this;
  }

}

let fib = new Fib();

fib.next() //{ done: false, value: 0 }
fib.next() //{ done: false, value: 1 }
fib.next() //{ done: false, value: 1 }
fib.next() //{ done: false, value: 2 }
fib.next() //{ done: false, value: 3 }
fib.next() //{ done: false, value: 5 }

let fibMax50 = new Fib(50);
console.log(Array.from(fibMax50)); // [ 0, 1, 1, 2, 3, 5, 8, 13, 21, 34 ]

let fibMax21 = new Fib(21);
for(let num of fibMax21) {
  console.log(num); //Prints fibonacci sequence 0 to 21
}

ES5 λŒ€μƒμœΌλ‘œ 반볡자λ₯Ό μ‚¬μš©ν•˜λŠ” μ½”λ“œ λ§Œλ“€κΈ°

μœ„ μ˜ˆμ œλŠ” ES6 이상 λŒ€μƒμ„ μš”κ΅¬ν•˜μ§€λ§Œ, λŒ€μƒ JS 엔진이 Symbol.iteratorλ₯Ό μ§€μ›ν•œλ‹€λ©΄ ES5 λŒ€μƒμ—μ„œλ„ μž‘λ™ν•  수 μžˆμŠ΅λ‹ˆλ‹€. μ΄λŠ” ES5 λŒ€μƒμ—μ„œ ES6 lib μ‚¬μš©ν•˜μ—¬ (es6.d.tsλ₯Ό ν”„λ‘œμ νŠΈμ— μΆ”κ°€) 컡파일 ν•˜λ©΄ λ©λ‹ˆλ‹€. 컴파일된 μ½”λ“œλŠ” node 4+, ꡬ글 크둬 그리고 λ‹€λ₯Έ λΈŒλΌμš°μ €μ—μ„œ λ™μž‘ν•  κ²ƒμž…λ‹ˆλ‹€.

results matching ""

    No results matching ""