问题
Considering this case of pattern matching:
foo match {
case x if expensiveCalculation(x).nonEmpty => // do something with expensiveCalculation(x)
...
}
is it possible to "label" or reuse the expensiveCalculation(x) after the =>?
Ideally I was expecting something like:
foo match {
case x val ec = expensiveCalculation(x); if ec.nonEmpty => // do something with ec
...
}
回答1:
You can write an extractor for the type of x (here assuming InputType):
object Expensive {
def unapply(x: InputType): Option[OutputType] = expensiveCalculation(x)
}
Now, you can use it in your pattern matching:
fooList match {
case _ :: Expensive(output) :: _ => ...
case _ :: x :: _ => ...
}
However, this is a cumbersome way to do what you want, if you do this for many calculations (you need to define an extractor every time).
You might do it once and for all by defining the following:
case class Comput[-A, +B](f: A => Option[B]) {
def unapply(a: A): Option[B] = f(a)
}
Now, you can use it as follow:
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
However, you cannot dispense from defining IntOf before using it in pattern matching (the compiler parser seems to be lost).
回答2:
I think you are trying to be more concise than possible.
Now let me replace your case with a more real example. Lets say you have following code,
fooList match {
case _ :: x :: _ if expensiveCalculation(x).nonEmpty => // do something with expensiveCalculation(x)
...
}
You should write it like this,
fooList match {
case _ :: x :: _ => expensiveCalculation(x) match {
case Some(calculationResult) => ....
case None =>
}
...
}
来源:https://stackoverflow.com/questions/40607586/scala-pattern-matching-with-reusable-condition