【发布时间】:2021-06-09 22:47:55
【问题描述】:
我想将以下代码从 Scala 2.12 迁移到 2.13
给定任何元组集合Coll[(A, B)] 和方法f: B => IterableOnce[C],我想通过在元组的第二个元素上应用f 来生成Coll[(A, C)]。
implicit class TuplesOps[A, B, Repr <: Traversable[(A, B)]](val s: TraversableLike[(A, B), Repr]) extends AnyVal {
def flatMapValues[C, That](f: B => TraversableOnce[C])(implicit bf: CanBuildFrom[Repr, (A, C), That]) =
s.flatMap { case (a, b) => f(b).map((a, _))}
}
我知道集合 API 在 2.13 中发生了变化,我读到:https://docs.scala-lang.org/overviews/core/custom-collection-operations.html
我已经尝试了 2 种实现方式
第一
import scala.collection.{ AbstractView, BuildFrom }
import scala.collection.generic.IsSeq
object Evidence extends App {
class TuplesOps[Repr, S <: IsSeq[Repr]](coll: Repr, seq: S) {
def flatMapValues[B, C, D, That](f: C => IterableOnce[D])(implicit bf: BuildFrom[Repr, (B, D), That], ev: seq.A =:= (B, C)): That = {
val seqOps = seq(coll)
bf.fromSpecific(coll)(new AbstractView[(B, D)] {
override def iterator: Iterator[(B, D)] = {
seqOps.flatMap { x => f(ev(x)._2).map((ev(x)._1, _))}.iterator
}
})
}
}
implicit def TuplesOps[Repr](coll: Repr)(implicit seq: IsSeq[Repr]): TuplesOps[Repr, seq.type] =
new TuplesOps(coll, seq)
List("a"->1, "b"->2).flatMapValues{(x:Int) => Seq.fill(x)("x")}
}
我有这个编译错误:
[error] /home/yamo/projects/perso/coll213/src/main/scala/example/Evidence.scala:22:37: diverging implicit expansion for type scala.collection.BuildFrom[List[(String, Int)],(B, String),That]
[error] starting with method Tuple9 in object Ordering
[error] List("a"->1, "b"->2).flatMapValues{(x:Int) => Seq.fill(x)("x")}
第二
import scala.collection.{ AbstractView, BuildFrom }
import scala.collection.generic.IsSeq
object Aux extends App {
type Aux[Repr, B, C] = IsSeq[Repr] { type A = (B, C)}
class TuplesOps[Repr, B, C, S <: Aux[Repr, B, C]](coll: Repr, seq: S) {
def flatMapValues[D, That](f: C => IterableOnce[D])(implicit bf: BuildFrom[Repr, (B, D), That]): That = {
val seqOps = seq(coll)
bf.fromSpecific(coll)(new AbstractView[(B, D)] {
// same as before
override def iterator: Iterator[(B, D)] = {
seqOps.flatMap { case (b, c) => f(c).map((b, _))}.iterator
}
})
}
}
implicit def TuplesOps[Repr, B, C](coll: Repr)(implicit seq: Aux[Repr, B, C]): TuplesOps[Repr, B, C, seq.type] =
new TuplesOps(coll, seq)
List("a"->1, "b"->2).flatMapValues(Seq.fill(_)("x"))
}
我有这个编译错误
[error] /home/yamo/projects/perso/coll213/src/main/scala/example/Aux.scala:24:24: value flatMapValues is not a member of List[(String, Int)]
[error] List("a"->1, "b"->2).flatMapValues(Seq.fill(_)("x"))
如果可能的话,你能帮我让这两个解决方案都起作用吗?
【问题讨论】:
-
你能用文字定义一下你原来的功能是做什么的吗?
-
给定一个元组集合,代码对元组的第二个元素应用一个函数(元组集合上的一种 flatMap)。
-
该方法应该适用于任何集合,而不仅仅是
List
标签: scala collections scala-2.13