我试图丰富所有TraversableOnce [String]对象,我无法找出构建迭代器的正确语法.这是我到目前为止:
class Exclaimer[R <: TraversableOnce[String]](val lines:R) {
import scala.collection.generic.CanBuildFrom
def exclaim(implicit bf:CanBuildFrom[R,String,R]):R = {
val b = bf(lines)
lines.foreach(b += _)
b.result
}
}
implicit def WrapExclaimer[R <: TraversableOnce[String]](lines:R) = new Exclaimer(lines)
Run Code Online (Sandbox Code Playgroud)
它适用于集合(即它返回与我给它相同的类的集合),但它不适用于迭代器,因为它Cannot construct a collection of type Iterator[java.lang.String] with elements of type String based on a collection of type Iterator[java.lang.String].我该如何解决?我正在使用Scala 2.9(编辑:我错误地写了2.8).
这是一些示例输出:
scala> List("a","b","c").exclaim
res5: List[java.lang.String] = List(a, b, c)
scala> Vector("a","b","c").exclaim
res6: scala.collection.immutable.Vector[java.lang.String] = Vector(a, b, c)
scala> List("a","b","c").iterator.exclaim
<console>:10: error: Cannot construct a collection of type Iterator[java.lang.String] with elements of type String based on a collection of type Iterator[java.lang.String].
List("a","b","c").iterator.exclaim
^
Run Code Online (Sandbox Code Playgroud)
你应该使用exclaim[That](implicit bf:CanBuildFrom[R, String, That])而不是CanBuildFrom[R,String,R].另请注意,有更多通用的方法来扩展类似集合的类 - IsTraversableOnce(以及IsTraversableLike)
import collection.generic.IsTraversableOnce
import collection.GenTraversableOnce
class Exclaimer[A, Repr](val lines: GenTraversableOnce[A]) {
import scala.collection.generic.CanBuildFrom
def exclaim[That](implicit bf:CanBuildFrom[Repr, String, That], e: A =:= String): That = {
val b = bf()
lines.foreach(s => b += e(s))
b.result
}
}
implicit def wrapExclaimer[Repr](r: Repr)(implicit fr: IsTraversableOnce[Repr]): Exclaimer[fr.A,Repr] =
new Exclaimer[fr.A, Repr](fr.conversion(r))
Run Code Online (Sandbox Code Playgroud)
此方法适用于Array:
Array("a","b","c").exclaim
// Array[String] = Array(a, b, c)
Run Code Online (Sandbox Code Playgroud)
这是您的初始实施(已修复).它适用Iterator,但失败,Array因为Array不是TraversableOnce:
class Exclaimer[R <: TraversableOnce[String]](val lines:R) {
import scala.collection.generic.CanBuildFrom
def exclaim[That](implicit bf:CanBuildFrom[R,String,That]):That = {
val b = bf(lines)
lines.foreach(b += _)
b.result
}
}
implicit def WrapExclaimer[R <: TraversableOnce[String]](lines:R) = new Exclaimer(lines)
scala> List("a","b","c").iterator.exclaim
res0: Iterator[String] = non-empty iterator
scala> Array("a","b","c").exclaim
<console>:10: error: value exclaim is not a member of Array[String]
Array("a","b","c").exclaim
^
Run Code Online (Sandbox Code Playgroud)
有没有IsTraversableOnce在scala 2.9.3,所以你必须使用你的初步做法的修正版本.但你会得到TraversableOnce而不是Iterator.
List("a","b","c").iterator.exclaim
// scala.collection.TraversableOnce[String] = non-empty iterator
Run Code Online (Sandbox Code Playgroud)
为了让Iterator你必须CanBuildFrom像这样创建自己的隐含:
import collection.generic.CanBuildFrom
import collection.mutable.Builder
import collection.immutable.VectorBuilder
implicit def iteratorCbf[A, B] = new CanBuildFrom[Iterator[A], B, Iterator[B]]{
def apply(): Builder[B, Iterator[B]] = new Builder[B, Iterator[B]]{
private[this] val inner = new VectorBuilder[B]
def +=(elem: B) = {
inner += elem
this
}
def clear(): Unit = inner.clear()
def result(): Iterator[B] = inner.result().iterator
}
def apply(i: Iterator[A]) = apply()
}
Run Code Online (Sandbox Code Playgroud)
不,你会得到Iterator[String]而不是TraversableOnce[String]:
List("a","b","c").iterator.exclaim
// Iterator[String] = non-empty iterator
Run Code Online (Sandbox Code Playgroud)
您应该将隐式iteratorCbf方法添加到Exclaimer类的伴随对象中.