我阅读了官方文档,但我还是不明白它是如何工作的.例如:
class A {
type Self
}
def seqToSet[T <: A](seq: Seq[T])
(implicit cbf: CanBuildFrom[Seq[T], T#Self, Set[T]]) {}
Run Code Online (Sandbox Code Playgroud)
上面的代码可以编译......但是怎么样?Scala如何知道Set可以从一个Seq?它怎么能确保T#Self(几乎任何类型)可以投入Set[T]?
一般情况下它不知道。你应该提供这样的CanBuildFrom.
对于像这样的简单情况,您可以使用breakOut:
class A1 extends A { type Self = A1 }
seqToSet(new A1 :: Nil)(collection.breakOut)
// compiles fine
Run Code Online (Sandbox Code Playgroud)
对于更复杂的情况:
case class A2(val i: Int) extends A {
type Self = Int
}
implicit val A2cbf = new CanBuildFrom[Seq[A2],A2#Self,Set[A2]] {
import scala.collection.mutable.Builder
class A2Builder extends Builder[A2#Self,Set[A2]] {
var es = List[A2]()
def +=(elem: A2#Self): this.type = { es ::= A2(elem); this }
def clear(): Unit = es = Nil
def result(): Set[A2] = es.toSet
}
def apply() = new A2Builder
def apply(from: Seq[A2]) = apply()
}
seqToSet(new A2 :: Nil)(collection.breakOut)
// compiles fine
Run Code Online (Sandbox Code Playgroud)
您应该提供Builder(使用CanBuildFrom),以便它A2#Self在方法中接受+=并Set[A2]作为结果返回。在代码示例中,它A2使用elem:创建新的A2(elem)。
让我们使用几乎相同的参数创建更有用的方法:
def seqToSet[T <: A](seq: Seq[T])(f: T => T#Self)
(implicit cbf: CanBuildFrom[Seq[T], T#Self, Set[T]]) = {
seq.map{f}: Set[T]
}
seqToSet(A2(1) :: A2(2) :: Nil){ a2 => a2.i + 1 }
// Set[A2] = Set(A2(3), A2(2))
Run Code Online (Sandbox Code Playgroud)
该方法提供了一些奇怪的A集合类型转换。
| 归档时间: |
|
| 查看次数: |
1908 次 |
| 最近记录: |