问题
I often read it's impossible to call Lambda functions on iterators. And I lived in that belief until now. However reading the book Professional Haxe by Franco Ponticelli and Lee-McColl-Sylvester about what makes an objet an Iterable or an Iterator made me think of one trick, that seems to work; at least in the simple case I just tested.
The trick is simply to declare an iterator() function inside the Iterator class, returning itself (weird yes, but not that incoherent).
I don't know if this will work in the general case, but this simple examples compiles and works fine on both Haxe 2 and Haxe 3 (http://try.haxe.org/#b764F):
using Lambda;
class IntIter2 {
var min : Int;
var max : Int;
public inline function new( min : Int, max : Int ) {
this.min = min;
this.max = max;
}
public inline function hasNext() { return min < max; }
public inline function next() { return min++; }
// here goes the magic/weirdness/abomination
public function iterator():IntIter2 { return this; }
}
class Test {
public static function main() {
var evenNumbers = new IntIter2(3, 10)
.filter( function (n:Int):Bool return n % 2 == 0 )
.list() // unneeded, in fact...
;
trace(evenNumbers.toString());
// list even numbers in the series, ie {4, 6, 8}
}
}
Why it works (at least here)
"In the haXe standard library, two very commonly used typedefs are defined: Iterator and Iterable.
Their definition is as follows:
typedef Iterator<T> = {
function hasNext() : Bool;
function next() : T;
}
typedef Iterable<T> = {
function iterator() : Iterator<T>;
}
" - Haxe Professional by Franco Ponticelli and Lee-McColl-Sylvester
Therefore adding iterator() to an Iterator class makes it Iterable, and usable with Lambda functions. Or is that always so simple?
回答1:
Check out this (open) issue on the Haxe repository:
Lambda should support Iterator as well as Iterable #1914
The final comment in the thread is actually what you're suggesting - and it could work, but changing the definition of "Iterator" so that every iterator is itself "iterable" is a breaking change and won't likely be changed during Haxe 3. Maybe for Haxe 4 :)
The other option is using abstracts, which allow implicit casting, to create a type "Iter" that works with both Iterable and Iterator:
abstract Iter<T>(Iterator<T>) from Iterator<T> to Iterator<T> {
inline function new(it:Iterator<T>)
this = it;
@:from static public inline function fromIterable(it:Iterable<T>) {
return new Iter(it.iterator());
}
}
I wrote about this in a comment on that issue: https://github.com/HaxeFoundation/haxe/issues/1914#issuecomment-19380450
You could use Iter to create your own custom Lambda helper that works with both Iterable and Iterator.
Good luck :)
来源:https://stackoverflow.com/questions/25648390/lambda-iteration-over-an-iterator-not-an-iterable