scala.collection.TraversableView.NoBuilder如何工作?

Pau*_*per 6 collections scala

我读了

我想我有点处理canBuildFrom.

但后来我查看了源码TraversableView,我看到了:

object TraversableView {
  class NoBuilder[A] extends Builder[A, Nothing] {
    def +=(elem: A): this.type = this
    def iterator: Iterator[A] = Iterator.empty
    def result() = throw new UnsupportedOperationException("TraversableView.Builder.result")
    def clear() {}
  }
  type Coll = TraversableView[_, C] forSome {type C <: Traversable[_]}
  implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, TraversableView[A, Traversable[_]]] =
    new CanBuildFrom[Coll, A, TraversableView[A, Traversable[_]]] {
      def apply(from: Coll) = new NoBuilder
      def apply() = new NoBuilder
    }
}
Run Code Online (Sandbox Code Playgroud)

TraversableView甚至这样的工作怎么样?似乎这里什么也没发生(NoBuilder似乎恰当地命名).

可能有人解释(1),该函数NoBuilder在这里踢球和(2)如何map,filter等等仍然可以正常工作?

axe*_*l22 5

NoBuilder存在,使客户可以把Scala的意见,如果他们改造时他们正常的集合.它是一个虚拟实现,允许TraversableView扩展Traversable和调用方法,map而不知道集合是视图还是普通集合.

更长的解释

当你打电话map,flatMap或者scanLeft(称为变压器上的斯卡拉收集操作),一个CanBuildFrom隐含参数会自动解决.该CanBuildFrom对象是对象的抽象工厂Builder.

大多数Scala集合用于通过调用buidler Builders来添加元素+=并生成新集合result.例如,给定一个构建器对象b,map这样做:

def map[S, That](f: T => S)(implicit cbf: CanBuildFrom[Repr, S, That]) = {
  val b: Builder[S, That] = cbf(this)
  for (x <- this) b += f(x)
  b.result
}
Run Code Online (Sandbox Code Playgroud)

视图上的Transformer操作不会实例化新集合.相反,他们创造了一个懒惰的视图.例如,map做这样的事情:

def map[S, That](f: T => S)(implicit cbf: CanBuildFrom[Repr, S, That]) = new TraversableView {
  def foreach[U](forFunc: T => U): Unit = for (x <- self) forFunc(f(x))
}
Run Code Online (Sandbox Code Playgroud)

请注意,map在视图上具有相同的签名,但并没有真正调用+=result对建设者.因此,NoBuilder视图中使用的并不真正需要存储元素或返回集合,它只是一个虚拟的方法永远不会被调用.

相同的签名允许在客户端代码中写入:

def foo(xs: Traversable[Int]) = xs.map(_ + 1)
foo(0 until 100)
foo((0 until 100).view)
Run Code Online (Sandbox Code Playgroud)