【问题标题】:In Scala 2.8 collections, why was the Traversable type added above Iterable?在 Scala 2.8 集合中,为什么在 Iterable 之上添加了 Traversable 类型?
【发布时间】:2011-02-05 20:09:01
【问题描述】:

我知道要成为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
}

【问题讨论】:

  • Traversable 在 Ch. 24 Scala 编程,第 2 版;在某些情况下,有效地实现foreachiterator 更容易。
  • 关于最后一个问题:github.com/scala/scala/pull/5101

标签: scala scala-2.8 scala-collections


【解决方案1】:

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

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

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

  • 希望通过 foreach 而不是通过迭代器来实现某些东西所带来的效率提升(在当前的 HotSpot 编译器中未必实际证明了收益)

【讨论】:

  • 请注意,在 Scala 2.13 集合重写中,我们再次摆脱了 Traversable 并回到基于迭代器的设计。
【解决方案2】:

我怀疑一个原因是,为具有抽象 foreach 方法的集合编写具体实现要比为具有抽象 iterator 方法的集合更容易。例如,在 C# 中,您可以编写实现 IEnumerable&lt;T&gt;GetEnumerator 方法,就好像它是 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)
}

【讨论】:

  • 我对 scala 还很陌生,但是由于您实际上并没有返回任何东西,所以您就不能写 def foreach[U](f: A =&gt; U){f(t1); f(t2); f(t3) } 吗?
  • foreach 声明它返回Unit 并因此丢弃U 类型的主体块f(t3) 的结果。
【解决方案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 中捕获它并返回。

【讨论】:

  • 其实你在scala中的return是错误的。 Scala 确实支持非本地返回。
  • 呃,这太令人惊讶了,你是对的。这一直有效吗??
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-02-24
  • 1970-01-01
  • 1970-01-01
  • 2011-02-01
  • 2012-01-24
  • 1970-01-01
  • 2013-04-10
相关资源
最近更新 更多