【问题标题】:Scala - extractor unapply confusionScala - 提取器不适用混淆
【发布时间】:2017-03-31 18:36:33
【问题描述】:

我正在尝试编写一个提取器,用于匹配多参数案例类。简化示例:

case class X(p1: String, p2: Int)

我希望每个提取器对象都为 p1 定义一个固定值,而 p2 是在使用时定义的。 (A、B等不能是case类和子类X,我也想用X(,)作为case) 应用方法示例:

object A {
  def apply(p2: Int): X = X("A", p2)
}

object B {
  def apply(p2: Int): X = X("B", p2)
}

...

对于模式匹配,我希望它们像这样匹配:

X("A", 2) match {
  case A(2) => true // <- should match: p1="A" and p2=2
  case A(_) => true // <- should match: p1="A" and p2=_
  case X("A", _) => true // <- should match: p1="A" and p2=_
  case A(1) => false // <- should not match
  case B(2) => false // <- should not match: p1="B" and p2=2
}

我知道我需要在AB 等中定义unapply 方法,但我完全搞不懂签名和逻辑应该是什么:

object A {
  def unapply(x: ???): Option[???] = {
    ???
  } 
}

请帮忙?

【问题讨论】:

    标签: scala pattern-matching


    【解决方案1】:

    unapply 接受 Any 并返回您要提取的任何内容的 Option。在您的情况下,这将是:

    scala> case class X(p1: String, p2: Int)
    defined class X
    
    scala> object A {
         |   def unapply(target: Any): Option[Int] =
         |     PartialFunction.condOpt(target) {
         |       case X("A", p2) => p2
         |     }
         | }
    defined module A
    
    scala> val A(x) = X("A", 1)
    x: Int = 1
    
    scala> val A(x) = X("B", 1)
    scala.MatchError: X(B,1) (of class X)
    ...
    

    但老实说,您提出的示例可以在没有AB 的情况下重写:

    X("A",2) match {
      case X("A", 2) => true
      case X("A", 1) => false
      case X("A", _) => true
      case X("B", 2) => false
    }
    

    【讨论】:

    • 在第一个例子中,我经常使用PartialFunction.condOpt来避免写入unapply的默认情况(这里:PartialFunction.condOpt(target) {case X("A", p2) =&gt; Some(p2)};你也可以导入PartialFunction._)。
    • 如此简单!谢谢!顺便说一句,我知道这个例子可以这样写,但这个例子被简化了。提取器的主要目的是封装不容易调用的参数组合。
    • @HeikoSeeberger 可能我们可以将 PartialFunction 示例添加到答案中,以使其更具可见性(我可以对其进行编辑,但这是您的答案,所以这取决于您);)
    • 我想添加一个没有参数的案例类,unapply 返回一个Boolean
    • unapply 可以采用类型参数(即比Any 更严格的参数),甚至是类型参数!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多