Scala:与可重用条件匹配的模式

时间:2016-11-15 10:33:28

标签: scala pattern-matching

考虑到这种模式匹配的情况:

foo match {
    case x if expensiveCalculation(x).nonEmpty => // do something with expensiveCalculation(x)
...
}

可以在expensiveCalculation(x)之后“标记”或重复使用=>吗?

理想情况下,我期待的是:

foo match {
        case x val ec = expensiveCalculation(x); if ec.nonEmpty => // do something with ec
    ...
    }

2 个答案:

答案 0 :(得分:1)

您可以为x类型编写一个提取器(此处假设为InputType):

object Expensive {
  def unapply(x: InputType): Option[OutputType] = expensiveCalculation(x)
}

现在,您可以在模式匹配中使用它:

fooList match {
  case _ :: Expensive(output) :: _ => ...
  case _ :: x :: _ => ...
}

然而,如果您为许多计算执行此操作(这需要每次都定义一个提取器),这是一种执行您想要的操作的麻烦方式。

您可以通过定义以下内容一劳永逸地执行此操作:

case class Comput[-A, +B](f: A => Option[B]) {
  def unapply(a: A): Option[B] = f(a)
}

现在,您可以按照以下方式使用它:

val intString = "10"
val IntOf = Comput[String, Int](s => Try(s.toInt).toOption)

intString match {
  case IntOf(x) => x
  case other => 0
} // returns 10: Int

但是,在模式匹配中使用它之前,你不能免除定义IntOf(编译器解析器似乎丢失了)。

答案 1 :(得分:0)

我认为你试图比可能更简洁。

现在让我用一个更实际的例子来代替你的案例。假设你有以下代码,

:java-source-paths ["java/src"]

你应该这样写,

fooList match {
  case _ :: x :: _ if expensiveCalculation(x).nonEmpty => // do something with expensiveCalculation(x)
  ...
}