如何构造一个空的 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()
通常 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()