Lambda iteration over an Iterator (not an Iterable)

时光毁灭记忆、已成空白 提交于 2019-12-10 22:34:02

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!