我们可以在匹配中的护卫中重复使用中间变量吗?

时间:2015-07-04 04:37:29

标签: scala

假设我有一个方法foo

def foo(i:Int):Option[Int] = ??? // some code

现在,我想对Seq Int进行操作,如下所示:

Seq(1, 2).map{
  case int => foo(int)
}.collect{
  case Some(int) => int
}

结合这种方法的一种方法是:

Seq(1, 2).collect{
  case int if foo(int).isDefined => foo(int)
}

有什么方法可以避免两次致电foo吗?

所以基本上我希望在foo(int)的LHS上定义=>作为准备在RHS上使用的变量,而不是必须再次计算它。

2 个答案:

答案 0 :(得分:1)

foo(int)仅存在于if的范围内,所以没有。我不认为这是可能的。一般情况下,我可能会使用类似于您使用mapcollect的第一个代码块的内容,因为foo仅在该上下文中调用一次。

在某些情况下,也可以完全重新定义问题。例如,可以使用flatMap

缩短此值
def foo(i: Int): Option[Int] = Option(i).filter(_ > 1)

scala> Seq(1, 2).flatMap(foo)
res0: Seq[Int] = List(2)

答案 1 :(得分:1)

对于您提供的案例,如果foo是部分函数,​​则可以执行

Seq(1, 2).collect{foo}

方便的是,我们可以使用foo

foo变成这样的部分函数(仅在Some(...)返回Function.unlift时定义)

让我们定义合适的foo

def foo(i:Int) = i match { case 1 => Some(42) ; case _ => None }

并测试它

Seq(1, 2).collect{
  case int if foo(int).isDefined => foo(int)
}
// Seq[Option[Int]] = List(Some(42))

现在" unlift"它是一个部分功能

val partialFoo = Function.unlift(foo)

并测试:

Seq(1, 2).collect{partialFoo}
// Seq[Int] = List(42)

所以你没有得到包含在Some(...)中的价值,但我认为无论如何你都会打开它,因为原始代码会包含Some(...)

中的每个元素