通常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()
答案 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()