【问题标题】:Scala implicit unapplyScala 隐式取消应用
【发布时间】:2014-06-24 01:54:23
【问题描述】:

我试图将一个类实例隐式解构为一个元组,以创建更好的 DSL 语法。

这是我正在尝试做的一个简化示例:

class Pair[A,B](a: A, b: B){
  def left = a
  def right = b
}
val pair = new Pair(1,2)
implicit def unpair[T1 <: Int, T2 <: Int](p: Pair[T1,T2]) = {
  (p.left, p.right)
}
val(a,b) = pair

结果:

error: constructor cannot be instantiated to expected type;
 found   : (T1, T2)
 required: Pair[Int,Int]

我知道我可以使用 unapply 方法定义一个伴随对象并手动处理解构(或显式调用上面的隐式),但这会产生不需要的样板。

编辑 好的,只是为了提供更多上下文,Pair 嵌入在实现 map、flatMap 和 withFilter 的实例中(即用于理解)。因此,所需的用法类似于:

val q = for{
  (a,b) <- tableA join tableB on(...)
  (c,d) <- tableC leftJoin tableD on(...)
  ....
} yield(a,b,c,d,...)

我想避免的是让 Pair 成为一个案例类(或向现有的 Pair 类添加一个自定义伴随对象)并且每次我加入表格时都必须Pair(a,b) &lt;- tableA join tableB on(...)(阅读:经常)

原创

有没有办法在 Scala 2.10 或 2.11 中实现这一点?从 2.8/2.9 天开始有一些较旧的 SO 线程表明此功能是不可能的,但我希望从那时起情况有所改变,或者有可用的解决方法。

【问题讨论】:

    标签: scala implicit boilerplate unapply


    【解决方案1】:

    您需要明确设置 a 和 b 的类型:

     val(a,b): (Int, Int) = pair
    

    【讨论】:

    • 很有趣,尽管在 DSL 的上下文中,这最终会创建比手动取消应用更多的样板。例如val(u,o): (Users,Orders) = pair, vs. val(u,o) = unpair(pair)
    • 所以,我认为在这种情况下你需要使用带有 unapply 的伴随对象。原因 val (a,b) ...它是模式匹配,而 unapply 就是为此而设计的。在 DSL 的上下文中,我认为您需要使用自己的域和方法进行更具体的类型推断
    • 查看实际用例的更新问题。可能是对的:伴生对象,希望隐式可以去掉额外的步骤......
    • 在更新的情况下,尝试设置 q 的类型 :) 或者如果 q 由方法返回,则设置方法的返回类型。实际上,如果你想使用隐式转换,我认为你无论如何都需要设置一些东西的类型。
    【解决方案2】:

    如果您只想提取左右(我从您的示例中猜测),为什么不使用更少的代码来解决您的问题:

    case class Pair[A, B](left: A, right: B)
    
    val pair = Pair(1, 2)
    
    val Pair(a, b) = pair
    
    println(a, b)
    

    【讨论】:

    • 对,这就是我对伴随对象想法的理解(Pair 实际上还有其他几个字段,所以它看起来更像 Pair(a,b,,, ,) 与案例类的默认伴随对象)。在 DSL Pair 的上下文中,它包含在实现 map、flatMap 和 withFilter 的包装器中。因此,在理解范围内,我将有几对要取消应用,并且 Pair(a,b)
    猜你喜欢
    • 2015-10-19
    • 2020-12-08
    • 2017-05-11
    • 1970-01-01
    • 2017-04-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多