如何组合(以一种很好的方式)两个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
答案 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, _) => {}
}
如果内部匹配器只有很少的选项(在这种情况下为c
和d
),它看起来很好(这可能就是你想要的),但它会导致代码重复(重复模式{{ 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
。