Can we reuse the intermediate variable from inside the guard inside the match?
Let's say I have a method foo
like:
def foo(i:Int):Option[Int] = ??? // some code
Now I want to work with Seq
from Int
like this:
Seq(1, 2).map{
case int => foo(int)
}.collect{
case Some(int) => int
}
One way to combine this:
Seq(1, 2).collect{
case int if foo(int).isDefined => foo(int)
}
Is there a way to avoid being called foo
twice?
So, basically I want to foo(int)
be defined in the LHS =>
as a variable ready to be used in the RHS, instead of having to evaluate it again.
source to share
foo(int)
exists only within the area if
, so no. I do not think that's possible. In general, I would probably use something similar to the first block of code you are using map
and collect
since it foo
is only called once in this context.
In some cases, it may also be possible to re-formulate the problem as a whole. For example, here it can be shortened with flatMap
:
def foo(i: Int): Option[Int] = Option(i).filter(_ > 1)
scala> Seq(1, 2).flatMap(foo)
res0: Seq[Int] = List(2)
source to share
In the case you gave, if foo
was a partial function, you could just do
Seq(1, 2).collect{foo}
Conveniently, we can turn foo
into a partial function like this (defined only where it foo
returns Some(...)
) usingFunction.unlift
Determine the appropriate foo
def foo(i:Int) = i match { case 1 => Some(42) ; case _ => None }
and test it
Seq(1, 2).collect{
case int if foo(int).isDefined => foo(int)
}
// Seq[Option[Int]] = List(Some(42))
Now "undo" it to a partial function
val partialFoo = Function.unlift(foo)
and check that:
Seq(1, 2).collect{partialFoo}
// Seq[Int] = List(42)
This way you won't get the value enclosed in Some(...)
, but I assume you would expand it since your original code would have each item inSome(...)
source to share