在Scala 2.8集合中,为什么Traversable类型添加到Iterable之上?

时间:2010-04-08 18:16:36

标签: scala scala-2.8 scala-collections

我知道要成为Traversable,您只需要foreach方法。 Iterable需要iterator方法。

Scala 2.8集合SID和“与类型战斗的Bitrot”论文基本上都没有提到为什么添加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
}

3 个答案:

答案 0 :(得分:11)

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

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

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

  • 希望通过foreach而不是通过迭代器实现一些功能来提高效率(目前的HotSpot编译器尚未实际获得增益)

答案 1 :(得分:4)

我怀疑一个原因是,使用抽象foreach方法为具有抽象iterator方法的方法编写具体实现要容易得多。例如,在C#中,您可以使用GetEnumerator IEnumerable<T>方法编写实现,就好像它是foreach方法一样:

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

(编译器生成一个适当的状态机来驱动IEnumerator的迭代。)在Scala中,您必须编写自己的Iterator[T]实现来执行此操作。对于Traversable,您可以执行与上述实现相同的操作:

def foreach[U](f: A => U): Unit = {
  f(t1); f(t2); f(t3)
}

答案 2 :(得分:-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中捕获它并返回。