我可以在Scala案例匹配中存储中间结果吗?

时间:2018-03-30 16:59:39

标签: scala

说我有这个:

def expensiveTest(t: String): Option[Int] = {...}
// myList: List[String]
myList.collectFirst {
  case x if expensiveTest(x).isDefined => expensiveTest(x).get
}

这样的东西有效,但是......我必须两次调用expensiveTest()。有没有办法将看守的调用结果保存到=>右侧的昂贵测试?

3 个答案:

答案 0 :(得分:3)

将列表切换为惰性流并使用map/head可能是另一种选择:

myList.toStream.flatMap { case x => expensiveTest(x) }.head

答案 1 :(得分:1)

是的,还有办法。我们可以使用提取器模式

object ExpensiveTest {
  unapply(x: String): Option[String] = if (x.isEmpty) None else Some(x) // Some logic
}

myList.collectFirst {
  case ExpensiveTest(nonEmptyString) => nonEmptyString
}

答案 2 :(得分:0)

Xavier的解决方案很好但如果myList为空则会失败。另一种替代方法是使用尾递归:

import scala.annotation.tailrec
  val l = List(1,2,3,4,5)
  def expensiveTest(t: Int): Option[Int] = if(t % 2 == 0) Some(t) else None
  @tailrec
  def f(l: List[Int]): Option[Int] = {
    l match {
      case Nil => None
      case h :: t => expensiveTest(h) match {
        case None => f(t)
        case x => x
      }
    }
  }

scala> f(l)
res0: Option[Int] = Some(2)