将两种匹配模式合二为一

时间:2012-02-29 14:29:15

标签: scala

如何组合(以一种很好的方式)两个Scala match'es?

首先,我必须测试Option是否是有效值:

myOption match {
  case Some(op) =>
    doSomethingWith(op)
  case None =>
    handleTheError()

然后如果op有效,我想测试另一种模式:

Path(request.path) match {
  case "work" => {
    println("--Let's work--")

  }
  case "holiday" => {
    println("--Let's relax--")
  }
  case _ => {
    println("--Let's drink--")
  }
}

我可以将它们组合起来:

myOption match {
  case Some(op) =>
    doSomethingWith(op)
    Path(request.path) match {
      case "work" => {
        println("--Let's work--")          
      }
      case "holiday" => {
        println("--Let's relax--")
      }
      case _ => {
        println("--Let's drink--")
      }
    }
  case None =>
    handleTheError()

但是,这感觉很草率。是否有更好的方式以某种方式组合它们。

更新

道歉,我应该更好地解释一下。我实际上试图找出是否存在用于简化(或分解)这些控制结构的已知模式。例如(想象一下):

x match {
 case a => {
   y match {
    case c => {}
    case d => {}
   }
 }
 case b => {}
}

等于

x -> y match {
  case a -> c => {}
  case a -> d => {}
  case b => {}
}

如果有人已经确定了控制流的一些重构模式,那我只是在徘徊,就像代数2(x + y) = 2x + 2y

2 个答案:

答案 0 :(得分:9)

你可以做到

myOption map { success } getOrElse handleTheError

scalaz

myOption.cata(success, handleTheError)

其中success类似于

def success(op: Whatever) = {
  doSomethingWith(op)
  Path(request.path) match {
    case "work"    => println("--Let's work--")
    case "holiday" => println("--Let's relax--")
    case _         => println("--Let's drink--")      
  }
}

更新

您的伪代码

x -> y match {
  case a -> c => {}
  case a -> d => {}
  case b => {}
}

可以直接翻译为scala为

(x, y) match {
  case (a, c) => {}
  case (a, d) => {}
  case (b, _) => {}
}

如果内部匹配器只有很少的选项(在这种情况下为cd),它看起来很好(这可能就是你想要的),但它会导致代码重复(重复模式{{ 1}})。所以,一般来说,我更喜欢a,或者在较小的函数上分离模式匹配器。但我再说一遍,在你的情况下它看起来很合理。

答案 1 :(得分:3)

如果审核者(您匹配的表达式)不相互依赖,即您可以独立计算它们,则可以通过将详细检查者包含在元组中来同时执行两个match es。

所以你的例子:

x match {
 case a => {
   y match {
    case c => fooC(...)
    case d => fooD(...)
   }
 }
 case b => fooB(...)
}

可以改写为:

(x,y) match {
  case (a, c) => fooC(...)
  case (a, d) => fooD(...)
  case (b, _) => fooB(...)
}

...只要y不依赖x