6.8 이터레이터(Iterators)

6.8 이터레이터(Iterators)

Haxe에서는 사용자 정의 이터레이터와 iterable 데이터 타입을 매우 쉽게 정의할 수 있어요. 이 개념들은 각각 타입 Iterator<T>Iterable<T>로 표현됩니다:

typedef Iterator<T> = {
  function hasNext():Bool;
  function next():T;
}

typedef Iterable<T> = {
  function iterator():Iterator<T>;
}

이 타입들 중 하나와 구조적으로 유니파이(structurally unifies)되는 어떤 클래스(class)for-루프로 반복할 수 있어요. 즉 클래스가 일치하는 반환 타입을 가진 hasNextnext 메서드를 정의하면 이터레이터로 간주되고, Iterator<T>를 반환하는 iterator 메서드를 정의하면 iterable 타입으로 간주됩니다.

class MyStringIterator {
  var s:String;
  var i:Int;

  public function new(s:String) {
    this.s = s;
    i = 0;
  }

  public function hasNext() {
    return i < s.length;
  }

  public function next() {
    return s.charAt(i++);
  }
}

class Main {
  static public function main() {
    var myIt = new MyStringIterator("string");
    for (chr in myIt) {
      trace(chr);
    }
  }
}

이 예제의 타입 MyStringIterator는 이터레이터 자격이 있습니다: Bool을 반환하는 hasNext 메서드와 String을 반환하는 next 메서드를 정의해 Iterator<String>과 호환됩니다. main 메서드는 그것을 인스턴스화한 뒤 반복합니다.

class MyArrayWrap<T> {
  var a:Array<T>;

  public function new(a:Array<T>) {
    this.a = a;
  }

  public function iterator():Iterator<T> {
    return a.iterator();
  }
}

class Main {
  static public function main() {
    var myWrap = new MyArrayWrap<Int>([1, 2, 3]);
    for (i in myWrap) {
      trace(i); // 1, then 2, then 3
    }
  }
}

여기서 MyArrayWrapiterator 메서드를 정의해 iterable 타입으로 간주됩니다. 전달된 배열의 이터레이터를 그대로 반환해, MyArrayWrap 인스턴스를 for-루프의 컬렉션으로 사용할 수 있게 합니다.

  • Iterator<T>: hasNext():Boolnext():T를 요구한다.
  • Iterable<T>: iterator():Iterator<T>를 요구한다.

특별한 지역 이터레이터(local iterator) 구조도 있습니다(원문 참조).

출처: Iterators

본문

Iterator와 Iterable

Iterator<T>hasNext():Boolnext():T를 요구하고, Iterable<T>iterator():Iterator<T>를 요구합니다. 이를 구조적으로 충족하는 클래스는 for-루프로 반복할 수 있어요.

예제

MyStringIteratorIterator<String>과 호환되는 이터레이터입니다. MyArrayWrapiterator()를 반환하는 iterable 타입으로, 내부 배열의 이터레이터를 재사용해요.

더 알아보기