我可以在Scala案例匹配中存储中间结果吗?
假设我有这个:我可以在Scala案例匹配中存储中间结果吗?,scala,Scala,假设我有这个: def expensiveTest(t: String): Option[Int] = {...} // myList: List[String] myList.collectFirst { case x if expensiveTest(x).isDefined => expensiveTest(x).get } 像这样的方法很管用,但是。。。我得给expensiveTest()打两次电话。是否有办法保存警卫调用expensiveTest的结果,以便在=>的右侧使用
def expensiveTest(t: String): Option[Int] = {...}
// myList: List[String]
myList.collectFirst {
case x if expensiveTest(x).isDefined => expensiveTest(x).get
}
像这样的方法很管用,但是。。。我得给expensiveTest()打两次电话。是否有办法保存警卫调用expensiveTest的结果,以便在=>的右侧使用?是的,有办法。我们可以使用提取器模式
object ExpensiveTest {
unapply(x: String): Option[String] = if (x.isEmpty) None else Some(x) // Some logic
}
myList.collectFirst {
case ExpensiveTest(nonEmptyString) => nonEmptyString
}
将列表切换到惰性流并使用
map/head
可能是另一种选择:
myList.toStream.flatMap { case x => expensiveTest(x) }.head
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)
不管怎么说,使用isDefined和get with选项都是不好的风格——可能有一种功能性的方法来编写它,效果会更好。能否共享更多上下文?如果myList为空,则此操作将失败;)@当然
.headOption
始终是一个备选方案。