Scala 如何反复调用一个方法,直到它返回一个包含None的Future值`

Scala 如何反复调用一个方法,直到它返回一个包含None的Future值`,scala,future,Scala,Future,如果有一个方法返回这样的未来 def remove(id: String): Future[Option[User]] = Future { // removes and returns the user identified by `id` } 。。。如何一次又一次地调用它,直到它返回一个不包含任何值的未来值 编辑 也许值得一提的是,我不需要收集结果。只要找到要删除的用户,我就需要调用该方法。我们的想法是在remove返回Future[None]时有一个停止的循环。StreamConti

如果有一个方法返回这样的未来

def remove(id: String): Future[Option[User]] = Future {
  // removes and returns the user identified by `id`
}
。。。如何一次又一次地调用它,直到它返回一个不包含任何值的未来值

编辑

也许值得一提的是,我不需要收集结果。只要找到要删除的用户,我就需要调用该方法。我们的想法是在remove返回Future[None]时有一个停止的循环。

StreamContinuous不断地做同样的事情,StreamtakeWhile在某一点停止它。


早些时候有人评论说没有意义

令我惊讶的是,懒散地消费期货没有捷径可走。Future.find类似于firstCompletedOf,但并不意味着按可遍历顺序查找first

另一种可能更可取的行为是,您得到一个未来,其中包含计算前缀的结果:

scala> :pa
// Entering paste mode (ctrl-D to finish)

  val work = new Work
  def g(ss: List[String]): Future[List[String]] = work.f("hello") flatMap {
    case None => Future.successful(ss)
    case Some(s) => g(s :: ss)
  }

// Exiting paste mode, now interpreting.

work: Work = Work@796d3c9f
g: (ss: List[String])scala.concurrent.Future[List[String]]

scala> g(Nil)
Calculated hello
Calculated hello
res3: scala.concurrent.Future[List[String]] = scala.concurrent.impl.Promise$DefaultPromise@99a78d7
Calculated hello
Calculated hello
Calculated hello

scala> Calculated hello
Calculated hello
Calculated hello
Calculated hello
Done.
利用未来:

scala> .value
res5: Option[scala.util.Try[List[String]]] = Some(Success(List(hello, hello, hello, hello, hello, hello, hello, hello, hello)))
这是:

import concurrent._, ExecutionContext.Implicits._
import java.util.concurrent.atomic._

val count = new AtomicInteger(10)

def f(s: String) = Future {
  if (count.decrementAndGet <= 0) None else Some(s)
}

Iterator continually {
  f("hello")
} takeWhile {
  Await.result(_, duration.Duration.Inf).nonEmpty
} foreach { _.map { _.map {
  println
}}

我希望这会有所帮助。

您想收集结果还是…不,我不需要收集结果-请参阅我的更新。与往常一样,downvoter没有发表评论。您必须阻塞以进行评估。使用Scalaz,你可以做一些类似StreamT.unfolm=>fhello.map\uuu.map\uuu->.toStream的事情,但是对了,我认为标准库在这里没有提供任何快捷方式。这与流的答案是一样的。我更新显示它阻塞,另一个不阻塞。现在来看一下布朗先生宣传的scalaz。顺便说一句,如果你想阻止,你最好坐在一个圈里。
scala> val work = new Work
work: Work = Work@1b45c0e

scala> Stream continually work.f("hello") takeWhile { x => Await.result(x, duration.Duration.Inf).nonEmpty }
Calculated hello
res0: scala.collection.immutable.Stream[scala.concurrent.Future[Option[String]]] = Stream(scala.concurrent.impl.Promise$DefaultPromise@66629f63, ?)

scala> .toList
Calculated hello
Calculated hello
Calculated hello
Calculated hello
Calculated hello
Calculated hello
Calculated hello
Calculated hello
Done.
res1: List[scala.concurrent.Future[Option[String]]] = List(scala.concurrent.impl.Promise$DefaultPromise@66629f63, scala.concurrent.impl.Promise$DefaultPromise@610db97e, scala.concurrent.impl.Promise$DefaultPromise@6f0628de, scala.concurrent.impl.Promise$DefaultPromise@3fabf088, scala.concurrent.impl.Promise$DefaultPromise@1e392345, scala.concurrent.impl.Promise$DefaultPromise@12f3afb5, scala.concurrent.impl.Promise$DefaultPromise@4ced35ed, scala.concurrent.impl.Promise$DefaultPromise@2c22a348, scala.concurrent.impl.Promise$DefaultPromise@7bd69e82)

scala> .foreach (Console println _.value.get)
Success(Some(hello))
Success(Some(hello))
[snip]
scala> :pa
// Entering paste mode (ctrl-D to finish)

  val work = new Work
  def g(ss: List[String]): Future[List[String]] = work.f("hello") flatMap {
    case None => Future.successful(ss)
    case Some(s) => g(s :: ss)
  }

// Exiting paste mode, now interpreting.

work: Work = Work@796d3c9f
g: (ss: List[String])scala.concurrent.Future[List[String]]

scala> g(Nil)
Calculated hello
Calculated hello
res3: scala.concurrent.Future[List[String]] = scala.concurrent.impl.Promise$DefaultPromise@99a78d7
Calculated hello
Calculated hello
Calculated hello

scala> Calculated hello
Calculated hello
Calculated hello
Calculated hello
Done.
scala> .value
res5: Option[scala.util.Try[List[String]]] = Some(Success(List(hello, hello, hello, hello, hello, hello, hello, hello, hello)))
import concurrent._, ExecutionContext.Implicits._
import java.util.concurrent.atomic._

val count = new AtomicInteger(10)

def f(s: String) = Future {
  if (count.decrementAndGet <= 0) None else Some(s)
}

Iterator continually {
  f("hello")
} takeWhile {
  Await.result(_, duration.Duration.Inf).nonEmpty
} foreach { _.map { _.map {
  println
}}