How does one combine (in a nice way) two Scala match'es?
First I have to test if an Option is a valid value:
myOption match {
case Some(op) =>
doSomethingWith(op)
case None =>
handleTheError()
Then if op was valid, I want to test for another pattern:
Path(request.path) match {
case "work" => {
println("--Let's work--")
}
case "holiday" => {
println("--Let's relax--")
}
case _ => {
println("--Let's drink--")
}
}
I could combine them like this:
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()
But, it feels sloppy. Is there a better way to combine them in some way or another.
Update
Apologies, I should have explained better. I'm actually trying to find out if there is a known pattern for simplifying (or factoring out) these control structures. For example (imagine this was true):
x match {
case a => {
y match {
case c => {}
case d => {}
}
}
case b => {}
}
equals
x -> y match {
case a -> c => {}
case a -> d => {}
case b => {}
}
I was just wandering if someone has already identified some refactoring patterns for control flow, much like algebra where 2(x + y) = 2x + 2y
You can do
myOption map { success } getOrElse handleTheError
or with scalaz
,
myOption.cata(success, handleTheError)
where success
is something like
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--")
}
}
Your pseudocode
x -> y match {
case a -> c => {}
case a -> d => {}
case b => {}
}
can be literally translated to scala as
(x, y) match {
case (a, c) => {}
case (a, d) => {}
case (b, _) => {}
}
It looks nice (and that's probably what you wanted) if inner matcher have only few options (c
and d
in this case), but it leads to code duplication (repeating of pattern a
). So, in general I'd prefer map {} getOrElse {}
, or separation of pattern-matchers on smaller functions. But I repeat, in your case it looks reasonable.
If the scrutinees (the expressions on which you match) do not depend on each other, i.e. you can compute them independently, you could perform both match
es at the same time by wrapping the scrutinees in a tuple.
So your example:
x match {
case a => {
y match {
case c => fooC(...)
case d => fooD(...)
}
}
case b => fooB(...)
}
could be rewritten as:
(x,y) match {
case (a, c) => fooC(...)
case (a, d) => fooD(...)
case (b, _) => fooB(...)
}
...as long as y
doesn't depend on x
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With