评估条件并将其结果绑定到模式匹配中?

Evaluate a conditional as well as bind its result in pattern match?

我反复发现自己在写类似这样的东西:

c match {
  case c if lengthyEvaluation1(c) > 0 => lengthyEvaluation1(c).toString
  case c if lengthyEvaluation2(c) > 0 => lengthyEvaluation2(c).toString
}

其中lengthyEvaluation1lengthyEvaluation2是计算时间不可忽略的函数,明显被调用了两次。有什么方法既可以创建一个作为 lengthyEvaluation(c) 结果的新变量,又可以检查条件吗?在 python 中有所谓的 'expression statement' 用于此目的,尽管它是最近的并且有点争议。或者这是一个不好的成语?

考虑惰性值定义,例如

lazy val a = lengthyEvaluation1(c)
lazy val b = lengthyEvaluation2(c) 

if (a > 0) 
  // use a
else if (b > 0)
  // use b
else
  ???

不,这是 Scala 模式匹配语法的弱点之一。您可以做的是使用自定义提取器:

class FunctionExtractor[A, B](f: A => B) {
  def unapply(a: A): Option[B] = Some(f(a))
}
val LengthyEvaluation1 = new FunctionExtractor(lengthyEvaluation1)
val LengthyEvaluation2 = new FunctionExtractor(lengthyEvaluation2)

c match {
  case LengthyEvaluation1(res) if res > 0 => res.toString
  case LengthyEvaluation2(res) if res > 0 => res.toString
}