6.7 Iterators
With Haxe it is very easy to define custom iterators and iterable data types. These concepts are represented by the types Iterator<T>
and Iterable<T>
respectively:
typedef Iterator<T> = {
function hasNext() : Bool;
function next() : T;
}
typedef Iterable<T> = {
function iterator() : Iterator<T>;
}
Any class which structurally unifies with one of these types can be iterated over using a for-loop. That is, if the class defines methods hasNext
and next
with matching return types it is considered an iterator, if it defines a method iterator
returning an Iterator<T>
it is considered an iterable type.
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);
}
}
}
The type MyStringIterator
in this example qualifies as iterator: It defines a method hasNext
returning Bool
and a method next
returning String
, making it compatible with Iterator<String>
. The main
method instantiates it, then iterates over it.
class MyArrayWrap<T> {
var a:Array<T>;
public function new(a:Array<T>) {
this.a = a;
}
public function iterator() {
return a.iterator();
}
}
class Main {
static public function main() {
var myWrap = new MyArrayWrap([1, 2, 3]);
for (elt in myWrap) {
trace(elt);
}
}
}
Here we do not setup a full iterator like in the previous example, but instead define that the MyArrayWrap<T>
has a method iterator
, effectively forwarding the iterator method of the wrapped Array<T>
type.