简体   繁体   English

Scala:递归Future的理解

[英]Scala: for-comprehension with recursive Future

The task is to realise recursive method, which returns Future任务是实现递归方法,返回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].并且由于这部分(“else recursive (result:::res, try + 1)”)代码失败并出现错误,因为它期望 Future[Seq[Result]],但实际上返回 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.据我了解,问题在于 yield-block 中的表达式必须返回 Seq[Result] 以供 Monad 在 Future 中进行后续包装。 But "recursive (result:::res, attempt + 1)" return Future.但是“递归 (result:::res, try + 1)”返回 Future。 So, instead of the expected Seq[Result] yield contain Future[Seq[Result]].因此,代替预期的 Seq[Result] 产量包含 Future[Seq[Result]]。

It there any way to work around this problem?有什么办法可以解决这个问题吗?

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:你真的不需要在这里理解,没有它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 :如果你出于某种原因偏向于理解,你仍然可以使用它,只需将大部分yield子句移到for

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM