如何构造一个空的 Iterable 子类,一般地,并且 Scala.js

How to construct an empty Iterable subclass, generically, and in 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

中工作

Update 我也试图以不同的方式使用它,但我忘了在最外层有隐式:

  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()

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()