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-루프로 반복할 수 있어요. 즉 클래스가 일치하는 반환 타입을 가진 hasNext와 next 메서드를 정의하면 이터레이터로 간주되고, 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
}
}
}
여기서 MyArrayWrap는 iterator 메서드를 정의해 iterable 타입으로 간주됩니다. 전달된 배열의 이터레이터를 그대로 반환해, MyArrayWrap 인스턴스를 for-루프의 컬렉션으로 사용할 수 있게 합니다.
Iterator<T>:hasNext():Bool과next():T를 요구한다.Iterable<T>:iterator():Iterator<T>를 요구한다.
특별한 지역 이터레이터(local iterator) 구조도 있습니다(원문 참조).
출처: Iterators
본문
Iterator와 Iterable
Iterator<T>는 hasNext():Bool과 next():T를 요구하고, Iterable<T>는 iterator():Iterator<T>를 요구합니다. 이를 구조적으로 충족하는 클래스는 for-루프로 반복할 수 있어요.
예제
MyStringIterator는 Iterator<String>과 호환되는 이터레이터입니다. MyArrayWrap는 iterator()를 반환하는 iterable 타입으로, 내부 배열의 이터레이터를 재사용해요.