unapply规则是否总是会返回一个选项?

时间:2009-12-14 20:36:32

标签: scala functional-programming pattern-matching

我尝试创建一个unapply方法用于模式匹配,我试图让它返回与Option不同的东西,但是,Eclipse显示这是一个错误。 unapply必须返回Option[T]吗?

是一条规则 编辑:这是我正在尝试使用的代码。我切换了上一节中的代码,以便unapply返回一个布尔值

import java.util.regex._

object NumberMatcher {
  def apply(x:String):Boolean = {
    val pat = Pattern.compile("\\d+")
    val matcher = pat.matcher(x)
    return matcher.find
  }

  def unapply(x:String):Boolean = {
    val pat = Pattern.compile("\\d+")
    val matcher = pat.matcher(x)
    return matcher.find
  }
}

object x {
  def main(args : Array[String]) : Unit = {
    val strings = List("geo12","neo493","leo")
    for(val str <- strings) {
      str match {
        case NumberMatcher(group) => println(group)
        case _ => println ("no")
      }
    }
  }
}

Eclipse说wrong number of arguments for object NumberMatcher。那是为什么?

4 个答案:

答案 0 :(得分:9)

如果您想使用unapply返回某些内容,请将其返回Some。返回Boolean只是测试是否可以匹配。

以下是模式匹配的翻译方式:

str match { 
  case NumberMatcher(group) => println(group)
  case _ => println("no")
}

假设NumberMatcher返回Option[...],它会执行:

val r1 = NumberMatcher.unapply(str)
if (r1 != None) {
  val group = r1.get
  println(group)
} else {
  println("no")
}

如果NumberMatcher返回布尔值,那么你可以让它收到一些东西。在这种情况下,会发生这种情况:

str match { 
  case NumberMatcher() => println("yes")
  case _ => println("no")
}

变为

val r1 = NumberMatcher.unapply(str)
if (r1) {
  println("yes")
} else {
  println("no")
}

请注意,这是非常肤浅的解释。大小写匹配可以测试常量,有额外的保护条件,替代方案,递归使用unapply,使用unapplySeq等。这里我只展示了解决特定问题的非常基本的用法。我强烈建议您寻找有关模式匹配的更全面的解释。

答案 1 :(得分:7)

再次查看此example。 我引用

  

应该选择unapply的返回类型如下:
      *如果只是一个测试,返回一个布尔值。例如情况偶()
      *如果它返回T类型的单个子值,则返回Option [T]
      *如果要返回多个子值T1,...,Tn,请将它们分组为可选的元组选项[(T1,...,Tn)]。

答案 2 :(得分:1)

当您定义unapply以返回Boolean时,您指示该模式没有任何匹配(或绑定)的通配符。所以这个unxtractor的case语句应该是case NumberMatcher => println(str),给它一个填充变量是错误的。

或者,要制作case NumberMatcher(group) => println(group),您需要定义unapply()以返回Option[String]

答案 3 :(得分:-2)

package com.tutorial.extracters
object ExtracterwithBooleanReturnType extends App {
import java.util.regex._
object NumberMatcher {
  def apply(x: String*) = {
    x
  }
  def unapply(x: String): Option[Boolean] = {
    val pat = Pattern.compile("\\d+")
    val matcher = pat.matcher(x)
    return Some(matcher.find)
 }
}

val strings = NumberMatcher("geo12", "neo493", "leo")
for (str <- strings) {
  str match {
  case NumberMatcher(group) => println(group)
  case _ => println("no")
}
}
}

我们也可以使用上面的代码来实现这个目标