20

我知道Traversable,你只需要一个foreach方法。Iterable需要一个iterator方法。

Scala 2.8 集合 SID 和“Fighting Bitrot with Types”论文基本上都没有提到为什么Traversable要添加这个主题。SID 只说“David McIver...提议 Traversable 作为 Iterable 的推广”。

我从关于 IRC 的讨论中模糊地收集到它与集合遍历终止时回收资源有关吗?

以下可能与我的问题有关。中有一些看起来很奇怪的函数定义TraversableLike.scala,例如:

def isEmpty: Boolean = {
  var result = true
  breakable {
    for (x <- this) {
      result = false
      break
    }
  }
  result
}

我认为有一个很好的理由不仅仅是写成:

def isEmpty: Boolean = {
  for (x <- this)
    return false
  true
}
4

3 回答 3

11

我在 IRC 上向 David McIver 询问了这个问题。他说他不再记得所有的原因,但它们包括:

  • “迭代器通常很烦人......实现”

  • 迭代器“有时是不安全的(由于循环开始和结束时的设置/拆卸)”

  • 通过 foreach 而不是通过迭代器来实现某些东西所希望的效率提升(收益不一定在当前的 HotSpot 编译器中实际展示)

于 2010-04-16T19:58:46.287 回答
4

I suspect one reason is that it's a lot easier to write a concrete implementation for a collection with an abstract foreach method than for one with an abstract iterator method. For example, in C# you can write the implementation the GetEnumerator method of IEnumerable<T> as if it were a foreach method:

IEnumerator<T> GetEnumerator() 
{
    yield return t1;
    yield return t2;
    yield return t3;
}

(The compiler generates an appropriate state machine to drive the iteration through the IEnumerator.) In Scala, you would have to write your own implementation of Iterator[T] to do this. For Traversable, you can do the equivalent of the above implementation:

def foreach[U](f: A => U): Unit = {
  f(t1); f(t2); f(t3)
}
于 2010-04-08T20:42:51.670 回答
-3

只是关于你的最后一个问题:

def isEmpty: Boolean = {
  for (x <- this)
    return false
  true
}

这被编译器粗略地翻译成:

def isEmpty: Boolean = {
  this.foreach(x => return false)
  true
}

所以你根本无法突破 foreach,isEmpty 将始终返回 true。

这就是为什么构造“hacky”Breakable 的原因,它通过抛出一个 Control-Exception 来打破 foreach,将其捕获breakable并返回。

于 2010-06-04T14:28:42.490 回答