【问题标题】:Migrating a generic append function to Scala 2.13 collections将通用附加函数迁移到 Scala 2.13 集合
【发布时间】:2019-08-08 07:18:24
【问题描述】:

我有以下扩展类,它向任何 SeqLike 添加了一个 myAppend 方法。

implicit class WithAppend[A, R](s: SeqLike[A, R]) extends AnyVal {
  def myAppend(i: A)(implicit cbf: CanBuildFrom[R, A, R]): R = s :+ i
}

如何将此代码移植到 Scala 2.13 并保留类似的性能特征?如果扩展类可以保持为AnyVal,则奖励积分

我尝试过的几件事:

class Extends1[R, S <: IsSeq[R]](c: R, isSeq: S) {
  def myAppend(a: isSeq.A): R = (isSeq(c) :+ a).asInstanceOf[R]
}

但是asInstanceOf 令人失望 - 它甚至安全吗?

我能做到:

class Extends3[S[_], A](c: SeqOps[A, S, S[A]]) {
  def myAppend(a: A): S[A] = c :+ a
}

但现在我们受限于 S[A] 形式的集合,而 Scala 2.12 代码可以采用任何 R

【问题讨论】:

  • myAppend:+ 的唯一区别似乎是它仅在返回类型与原始序列相同时可用。所以asInstanceOf 并不像打破唯一的用例那么令人失望......
  • 其他人可能无法回答这个问题,因为你还没有说出你想要完成的事情。很可能[A, S[_]](val s: SeqLike[A, S, S[A]]) 和跳过CanBuildFrom 可以正常工作,但谁知道呢,因为我们必须猜测你为什么想要myAppend 而不是仅仅:+ 开始。
  • @TravisBrown 更多背景信息:我正在致力于移植/改进 ScalaPB 的镜头功能。我想为Seq-ish 的字段提供一个扩展方法,它提供了对字段的修改:github.com/scalapb/ScalaPB/blob/…。我编辑了问题以阐明我的要求:asInstanceOf 安全吗?我们可以在任何R 上而不是S[A]s 上操作吗?
  • 您是否使用docs.scala-lang.org/overviews/core/… 作为您的向导?它最近才出现在网站上
  • @SethTisue - 是的,这是一本很棒的书。但是,在这种情况下,我在实施这些想法时遇到了一些问题:如果我同时得到 IsSeqBuildFrom,我怎么能要求它们具有相同的 ABuildFrom.fromSpecific 有一个似乎未使用的 from 参数 - 目前尚不清楚如何在这里使用 BuildFrom 以与调用 :+ 具有相似的性能

标签: scala scala-2.13


【解决方案1】:

我可以想出一个无需强制转换即可工作的方法签名和实现:

implicit class WithAppend[Repr](private val repr: Repr) extends AnyVal { 
  def myAppend[A0, C](a: A0)(
    implicit 
    isSeq: IsSeq[Repr]{ type A = A0 }, 
    b: BuildFrom[Repr, A0, C]
  ): C = b.fromSpecific(repr)(isSeq(repr) :+ a) 
}

很难保证它的性能,但我怀疑它会比你以前拥有的要差得多。另一种方法是b.newBuilder(repr).addAll(isSeq(repr)).addOne(a).result()

scala> List(1,2).myAppend(3)
res3: List[Int] = List(1, 2, 3)

scala> Vector(1,2).myAppend(3)
res4: scala.collection.immutable.Vector[Int] = Vector(1, 2, 3)

scala> "Strin".myAppend('g')
res5: String = String

【讨论】:

  • 谢谢!虽然很遗憾 myAppend 具有类型参数,其中所有类型都在隐式类范围内可用。可以把它们搬到那里吗?我想知道新集合是否应该为IsSeq 和朋友提供Aux 模式以简化这样的用例。
  • 如果你想让它成为一个值类,那几乎是不可能的。我尝试将其转换为具有 2 个参数和隐式定义的类,例如 docs.scala-lang.org/overviews/core/…,但我无法立即使其工作。但我认为这应该是可能的。
猜你喜欢
  • 2021-09-29
  • 2021-04-24
  • 2021-10-14
  • 2019-10-25
  • 2021-06-09
  • 2021-06-21
  • 2015-04-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多