Home > Software engineering >  Scala: for-comprehension with recursive Future
Scala: for-comprehension with recursive Future

Time:06-02

The task is to realise recursive method, which returns Future

def recursive (result:List[Result], attempt: Int):Future[Seq[Result]] = attempt match {
   case a if a < 3 => { 
       for {
            res <- retrive()
           } yield {
               if ((result:::res).size > 20) res
               else recursive (result:::res, attempt   1)          
           }
   }
   case => Future(Seq.empty)
}

And due to this part ("else recursive (result:::res, attempt 1)" ) code failed with error, as it expects Future[Seq[Result]], but in fact return Future[Object].

As I understand, the problem is that expression inside yield-block must return Seq[Result] for the subsequent wrapping by Monad in Future. But "recursive (result:::res, attempt 1)" return Future. So, instead of the expected Seq[Result] yield contain Future[Seq[Result]].

It there any way to work around this problem?

CodePudding user response:

The trick is to wrap the value you are returning in the terminal case into a future, so that the types match for both cases.

You don't really need a for-comprehension here, it would read a lot better without it IMO:

   retrieve.flatMap { 
      case r if r.size   result.size > 20 => Future.successful(result:::r) // you are not prepending result in your snippet, I think, it's a bug ...
      case r => recursive (result:::r, attempt   1)  
   }

If you are partial to for-comprehension for some reason, you can still use it, just need to move most of the yield clause inside the for:

    for {
       res <- retrieve()
       out <- if (res.size()   result.size() > 20) Future.successful(result:::res) 
              else recursive (result:::res, attempt   1) 
     } yield out
        
          
  • Related