scala - 隐式参数不适用于 unapply。如何从提取器中隐藏无处不在的参数?

标签 scala pattern-matching implicit extractor

显然,提取器对象中的 unapply/unapplySeq 不支持隐式参数。假设这里有一个有趣的参数 a 和一个令人不安的普遍存在的参数 b,在提取 c 时可以很好地隐藏它。

[ 编辑 ]:在我的 intellij/scala-plugin 安装中似乎有什么问题导致了这个问题。我无法解释。最近我的智能遇到了许多奇怪的问题。重新安装后,我无法再重现我的问题。确认 unapply/unapplySeq 确实允许隐式参数!谢谢你的帮助。

这不起作用(**编辑 :是的,确实如此):**

trait A; trait C; trait B { def getC(a: A): C }

def unapply(a:A)(implicit b:B):Option[C] = Option(b.getC(a))

在我对理想的提取器应该是什么样子的理解中,Java 人员的意图也很直观,这个限制基本上禁止依赖于附加参数的提取器对象。

您通常如何处理这种限制?

到目前为止,我有这四种可能的解决方案:

1)我想改进的最简单的解决方案:不要隐藏b,提供参数b和a,作为元组形式的unapply的正常参数:
object A1{ 
    def unapply(a:(A,B)):Option[C] = Option(a._2.getC(a._1)) }

在客户端代码中:
 val c1 = (a,b) match { case A1(c) => c1 }

我不喜欢它,因为有更多的噪音偏离 a 到 c 的解构在这里很重要。此外,由于必须说服 Java 人员实际使用此 Scala 代码,因此面临一个额外的综合新颖性(元组大括号)。他们可能会遇到反scala攻击“这到底是怎么回事?......为什么不首先使用正常方法并检查if?”。

2) 在一个类中定义提取器,封装对特定 B 的依赖,导入该实例的提取器。在导入站点对于 Java 人员来说有点不寻常,但是在模式匹配站点 b 隐藏得很好,并且直观地看出会发生什么。我最喜欢的。我错过了一些缺点?
class BDependent(b:B){ 
   object A2{ 
    def unapply(a:A):Option[C] = Option(b.getC(a))
         } }

在客户端代码中的用法:
val bDeps = new BDependent(someB)
import bDeps.A2 
val a:A = ...
val c2 = a match { case A2(c) => c }
}

3) 在客户端代码范围内声明提取器对象。 b 是隐藏的,因为它可以在本地范围内使用“b”。阻碍代码重用,严重污染客户端代码(另外,在代码使用之前必须说明)。

4) have unapply return Option of function B => C. 这允许导入和使用依赖于参数的提取器,而不直接将 b 提供给提取器,而是在使用时提供结果。 Java 人可能会被函数值的使用弄糊涂,b 不是隐藏的:
 object A4{
  def unapply[A,C](a:A):Option[B => C] = Option((_:B).getC(a))
   }

然后在客户端代码中:
 val b:B = ...
 val soonAC: B => C = a match { case A4(x) => x }
 val d = soonAC(b).getD ...

补充说明:
  • 正如 this answer 中所建议的,“ View 边界”可能有助于让提取器使用隐式转换,但这对隐式参数没有帮助。出于某种原因,我不喜欢使用隐式转换来解决。
  • 查看“上下文边界”,但它们似乎具有相同的限制,不是吗?
  • 最佳答案

    你的第一行代码在什么意义上不起作用?对于提取器方法的隐式参数列表,当然没有任意禁止。

    考虑以下设置(我使用普通的旧类而不是案例类来表明这里没有发生额外的魔法):

    class A(val i: Int)
    class C(val x: String)
    class B(pre: String) { def getC(a: A) = new C(pre + a.i.toString) }
    

    现在我们定义一个隐式 B值并使用您的 unapply 创建一个提取器对象方法:
    implicit val b = new B("prefix: ")
    
    object D {
      def unapply(a: A)(implicit b: B): Option[C] = Option(b getC a)
    }
    

    我们可以这样使用:
    scala> val D(c) = new A(42)
    c: C = C@52394fb3
    
    scala> c.x
    res0: String = prefix: 42
    

    正如我们所期望的那样。我不明白为什么你需要一个解决方法。

    关于scala - 隐式参数不适用于 unapply。如何从提取器中隐藏无处不在的参数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12338469/

    相关文章:

    scala - 在 Scala IDE 中使用 Akka

    scala - 为什么Unit可以赋值给一个Tuple而不会出现编译错误?

    javascript - 如何在带有模式的文本中查找数字并在 JavaScript 中更改它

    正则表达式作为 Lua 模式

    scala - 创建类型敏感函数而不更改父特征或案例类

    scala - 如何在集合中进行隐式转换?

    multithreading - 让 Actor sleep

    scala - 在 Scala 中一次捕获多个异常

    scala - 隐式转换、类型参数、重载和匿名函数语法

    list - 为什么 `Nil` 被定义为 `case object`