Dominykas Mostauskis
Dominykas Mostauskis

Reputation: 8125

Scala async calculation exercise

I have outlined the problem below. Method calculate represents a calculation that is to run subCalc1 and subCalc2 asynchroniously, and mainCalc that will be passed results from the last two 'sub' calculations. Significantly, before starting these calculations a preliminary calculation isCalcNecessary is to return a Boolean. If true, the calculation will continue and eventually return Future[Some[Result]]. If preliminary calculation returns false, it should return Future[None], as to illustrate that calculation was not necessary. This small algorithm should be maximally asynchronious.

def isCalcNecessary:Future[Boolean] = ...
def subCalc1(param:Param):Future[SubResult1] = ...
def subCalc2(param:Param):Future[SubResult2] = ...
def mainCalc(subResult1:SubResult1, subResult2:SubResult2):Future[Result] = .

def calcute(param:Param):Future[Option[Result]] = for {
  necessary <- isCalcNecessary(param)
  if necessary // this illustration fails at runtime if 'necessary' is false
  subResult1 <- subCalc1(param)
  subResult2 <- subCalc2(param)
  result <- mainCalc(subResult1, subResult2)
} yield Some(result)

The above illustration fails at runtime with (NoSuchElementException: Future.filter predicate is not satisfied (Future.scala:312)), if the if necessary conditional is not satisfied.

How would you write this algorithm?

Upvotes: 0

Views: 161

Answers (2)

pagoda_5b
pagoda_5b

Reputation: 7373

Another option would be to nest for-comprehensions

def calculate(param:Param):Future[Option[Result]] = for {
  necessary <- isCalcNecessary(param)
  endResult <- if (necessary) for {
      subResult1 <- subCalc1(param)
      subResult2 <- subCalc2(param)
      result     <- mainCalc(subResult1, subResult2)
    } yield Some(result)
    else future(None)
} yield endResult

Upvotes: 2

Alexey Romanov
Alexey Romanov

Reputation: 170735

isCalcNecessary(param).flatMap { necessary => 
  if (necessary) 
    for {
      subResult1 <- subCalc1(param)
      subResult2 <- subCalc2(param)
      result <- mainCalc(subResult1, subResult2)
    } yield Some(result)
  else
    future(None)
}

Upvotes: 2

Related Questions