如何在Scala.js中一般地构造一个空的Iterable子类

时间:2017-10-09 18:44:26

标签: scala scala-collections scala.js

通常breakout有助于从一个集合转换到另一个集合,但它似乎无法为C推断出必要的集合构造函数:

import scala.collection.breakOut

object Utils {

  implicit class IterableExtra[T, C[X] <: Iterable[X]](val list: C[T]) extends AnyVal {
    def empty: C[T] = Iterable.empty[T].map(x => x)(breakOut)

  }
}

理想情况下,这可以使用最少的反射,因此它可以在scala.js

中工作

更新我也尝试以不同的方式使用它,我忘了隐藏在最外层:

  def testIterableEmpty[B, I[X] <: Iterable[X]](implicit cbf: CanBuildFrom[I[B], B, I[B]]): I[B] = {
    def emptyIter: I[B] = cbf().result()
    emptyIter
  }


scala> val x: List[Int] = testIterableEmpty[Int, List]
x: List[Int] = List()

1 个答案:

答案 0 :(得分:1)

breakOut的定义如下:

def breakOut[From, T, To](implicit b: CanBuildFrom[Nothing, T, To]): CanBuildFrom[From, T, To]

所以它不能用于避免CanBuildFrom传递到您的empty方法 - 它本身需要一个。幸运的是,它很容易编写 - 你想从C[T]创建一个C[T],元素类型是T,所以:

def empty(implicit cbf: CanBuildFrom[C[T], T, C[T]]): C[T] =
      Iterable.empty[T].map(x => x)(breakOut)

因为你有一个CanBuildFrom实例,直接使用它的实现也很简单:

def empty(implicit cbf: CanBuildFrom[C[T], T, C[T]]): C[T] =
      cbf().result()