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.

+3


source to share


2 answers


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)

      

+1


source


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(...)

+1


source







All Articles