【问题标题】:Lambda iteration over an Iterator (not an Iterable)迭代器上的 Lambda 迭代(不是 Iterable)
【发布时间】:2014-10-28 04:39:57
【问题描述】:

我经常读到不可能在迭代器上调用 Lambda 函数。直到现在我都活在这种信念中。然而,阅读 Franco Ponticelli 和 Lee-McColl-Sylvester 所著的《Professional Haxe》一书,关于什么使对象成为 Iterable 或 Iterator 的内容让我想到了一个似乎有效的技巧;至少在我刚刚测试的简单案例中。

诀窍就是在 Iterator 类声明一个 iterator() 函数,返回 itself(很奇怪,但不是那么不连贯)。

我不知道这是否适用于一般情况,但这个简单的示例可以在 Haxe 2 和 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}
    }
}

为什么有效(至少在这里)

“在haXe标准库中,定义了两个非常常用的typedef:Iterator和Iterable。

它们的定义如下:

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

" - Franco Ponticelli 和 Lee-McColl-Sylvester 的 Haxe Professional

因此,将 iterator() 添加到 Iterator 类使其可迭代,并可与 Lambda 函数一起使用。还是总是这么简单?

【问题讨论】:

  • 编辑:我的测试表明它甚至适用于更复杂的情况(模板化迭代器类优于模板化类继承其他类等)。只要确保写function iterator():NameOfTheClass {} 而不是function iterator():Iterator&lt;SomeType&gt; {} 就可以了(否则在第二种情况下,它会抱怨迭代器没有Lambda.filter 或您尝试的任何其他同态方法using)。

标签: lambda iterator haxe iterable


【解决方案1】:

在 Haxe 存储库中查看这个(未解决的)问题:

Lambda should support Iterator as well as Iterable #1914

线程中的最后一条评论实际上是您的建议 - 它可以工作,但是更改“迭代器”的定义以使每个迭代器本身都是“可迭代的”是一个重大更改,并且不太可能被更改在 Haxe 3 期间。也许在 Haxe 4 中:)

另一种选择是使用允许隐式转换的抽象来创建可与 Iterable 和 Iterator 一起使用的类型“Iter”:

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());
  } 
}

我在关于这个问题的评论中写了这个:https://github.com/HaxeFoundation/haxe/issues/1914#issuecomment-19380450

您可以使用 Iter 创建自己的自定义 Lambda 帮助程序,该帮助程序可与 Iterable 和 Iterator 一起使用。

祝你好运:)

【讨论】:

  • 我关注了你的链接,这是一个很好的讨论。但我真的不明白你用abstractfrom Iterator&lt;T&gt; to Iterator&lt;T&gt; 的解决方案。我想这是 Haxe 3 中的新东西。我不知道这是否会在转换阶段引起问题,但如果不是,我认为所有迭代器都应该是可迭代的。在诸如 Java 之类的语言中将这两个概念分开是有意义的,但是对于称为 Haxe(“hacks”?)的语言,坚持迭代器的正统概念只是限制性的,所以我也提倡在 Haxe 中使用它4.
  • 顺便说一句,如果它们都是可迭代的,那真的会是一个突破性的变化吗?诚然,它会从根本上改变迭代器的概念,因此有充分的理由不这样做,但我没有立即看到它实际上会如何破坏事物(也许我没有足够的想象力:p)。跨度>
  • 唯一会破坏的是如果您有自定义迭代器。因此,如果我现在有一个匹配 Iterable 的类,但随后 Iterable 更改为也需要 iterator():Iterable 函数,那么我的自定义迭代器不再是迭代器。我个人没有在我的代码中使用自定义迭代器,但我相信有些人会这样做......除此之外它不会真正破坏任何东西:)
  • Jason:之前我倾向于认为它们没那么有用,但我最近将我的线条绘制功能移植到了一个迭代器,现在如果我想检测某个方向上的障碍物,例如投掷箭头,我不再需要计算线上的所有点。因此,对于带有网格的 2d 游戏,我认为自定义迭代器非常有用,如果它们可以与 Lambda 一起使用,那就更有用了。
猜你喜欢
  • 2015-09-09
  • 2013-06-19
  • 2019-06-25
  • 1970-01-01
  • 2018-02-16
  • 1970-01-01
  • 2017-01-17
  • 2011-08-19
  • 1970-01-01
相关资源
最近更新 更多