首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Scala中一对算子的++=

Scala中一对算子的++=
EN

Stack Overflow用户
提问于 2018-11-12 01:14:44
回答 1查看 74关注 0票数 1

我用Scala编写了以下内容:

代码语言:javascript
复制
implicit class Appender[A, B](x: (Growable[A], Growable[B])) {
  def ++=(y: (TraversableOnce[A], TraversableOnce[B])): (Growable[A], Growable[B]) =
    (x._1 ++= y._1, x._2 ++= y._2)
}

但是Scala不接受x._2 ++= y._2,抱怨说:Expression of type Growable.this.type doesn't conform to expected type Growable[B]

我也试过:

为此,IntelliJ建议返回类型的(Growable.this.type, Growable.this.type),这将导致其他问题。

我遗漏了什么?将此++=操作添加到2 GrowableTuple2中的正确方法是什么?

是否有一种方法可以编写这种“提升”,但也可以将其推广到操作(此处为++=)?这将是一些隐式Lift,它可以将操作从对内的类型传递到对类型本身。这在Scala中有可能吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-11-12 02:43:21

您的第一个代码片段对我来说编译和工作都很好,尽管IntelliJ对其进行了强调。

但是,这段代码的问题是,它丢失了关于第一对具体类型的信息。结果显示为不透明的(Growable[A], Growable[B])

为了保留类型,您可以使用类似于第二个片段的东西。问题是编译器似乎无法将隐式转换应用于一对Growable子类型。但是,如果您试图显式地创建Appender,它可以工作:

代码语言:javascript
复制
object Test {
  implicit class Appender[
    A, GA <: Growable[A],
    B, GB <: Growable[B]
  ](x: (GA, GB)) {
    def ++=(y: (TraversableOnce[A], TraversableOnce[B])): (GA, GB) = {
      (x._1 ++= y._1, x._2 ++= y._2)
    }
  }

  def main(args: Array[String]): Unit = {
    val a = (ArrayBuffer(1,2,3), ArrayBuffer("a","b","c"))
    println(new Appender(a).++=((List(4,5,6), List("d","e","f"))))
  }
}

您可以通过使用组合类型x定义GA with Growable[A]的部分来帮助编译器。在这种情况下,编译器使用声明的Growable[A]部分检测并正确应用隐式转换。您仍然可以访问完整类型的GA,以便从该方法返回:

代码语言:javascript
复制
object Test {
  implicit class Appender[
    A, GA <: Growable[A],
    B, GB <: Growable[B]
  ](x: (GA with Growable[A], GB with Growable[B])) {
    def ++=(y: (TraversableOnce[A], TraversableOnce[B])): (GA, GB) = {
      (x._1 ++= y._1, x._2 ++= y._2)
    }
  }

  def main(args: Array[String]): Unit = {
    val a = (ArrayBuffer(1,2,3), ArrayBuffer("a","b","c"))
    println(a ++= (List(4,5,6), List("d","e","f")))
  }
}

附加:

至于你的奖金问题,我不认为有一个简单的方法来自动创建所有的方法。也许你可以用宏做点什么,但我不确定。但是我相信您可以使用一些帮助方法来大大简化方法定义。没有那么多方法可以对Growable进行有意义的定义,因此我相信有一个完整的定义:

代码语言:javascript
复制
implicit class Appender[
  A, GA <: Growable[A]
](x: (GA with Growable[A], GA with Growable[A])) {
  private def wrap[B, R](f: GA => B => R): ((B, B)) => (R, R) =
    y => (f(x._1)(y._1), f(x._2)(y._2))

  val ++= = wrap(_.++=)
  val += = wrap(_.+=)

  def clear(): Unit = {
    x._1.clear()
    x._2.clear()
  }
}

如果你有其他手术

代码语言:javascript
复制
def myOpDef[A, GA <: Growable[A]](ga: GA, traversable: TraversableOnce[A]): GA = ???

您还可以将其添加到Appender定义中(但这似乎有点棘手):

代码语言:javascript
复制
val myOp = wrap(ga => myOpDef(ga, _))

代码语言:javascript
复制
val myOp = wrap(myOpDef[A, GA].curried)
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53254858

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档