我有一些副作用,
def f(): Future[Int] = {
val n = Random.nextInt()
println(s"Generated $n")
Future(n)
}
我想重复执行它,直到谓词返回true。
def success(n: Int): Boolean = n % 2 == 0
我的计划是构建Stream
结果
val s = Stream.fill(10)(f)
然后使用Future.find
获取满足谓词的第一个结果。
Future.find(s)(success) map println
问题是Future.find
并行运行所有期货,我希望它依次执行期货,直到谓词返回true。
scala> Future.find(s)(success) map println
Generated -237492703
Generated -935476293
Generated -1155819556
Generated -375506595
Generated -912504491
Generated -1307379057
Generated -1522265611
Generated 1163971151
Generated -516152076
res8: scala.concurrent.Future[Unit] = scala.concurrent.impl.Promise$DefaultPromise@37d28f02
Some(-1155819556)
问题是如何按顺序执行期货流,直到谓词返回true为止?标准或第三方库中是否有合适的功能?
答案 0 :(得分:4)
而不是使用Stream我建议使用另一种方法。使用The Future的过滤器并以递归方式恢复:
def findFirst[A](futureGen: => Future[A], predicate: A => Boolean): Future[A] = {
futureGen.filter(predicate).recoverWith { case _ => findFirst(futureGen, predicate) }
}
findFirst(f, success)
这会一个接一个地打电话给期货,直到'成功'将返回真实。
答案 1 :(得分:1)
首先,让我们不感兴趣的未来失败:
val s1 = s.map(_.filter(success))
现在你可以结合两个这样的未来,并使用fallbackTo
获得第一个成功的价值。只是折叠流,从一个已知不好的未来开始:
def firstSuccess[T](stream: Stream[Future[T]]): Future[T] =
if (stream.isEmpty)
Future.failed(new NoSuchElementException)
else
stream.head.fallbackTo(firstSuccess(stream.tail))
答案 2 :(得分:0)
如果我理解了这个问题,那么你将不得不阻止线程按顺序进行。您可以使用Await来实现这一目标。
scala> def f(): Future[Int] = {
| val n = Random.nextInt()
| println(s"Generated $n")
| Future(n)
| }
f: ()scala.concurrent.Future[Int]
scala> def success(n: Int): Boolean = n % 2 == 0
success: (n: Int)Boolean
scala> val s = Stream.fill(10)(f)
用你的方式,我得到了
scala> Future.find(s)(success) map println
Generated 551866055
Generated -561348666
Generated -1103407834
Generated -812310371
Generated -1544170923
Generated 2131361419
Generated -236722325
Generated -1473890302
Generated -82395856
Some(-561348666)
res16: scala.concurrent.Future[Unit] = scala.concurrent.impl.Promise$DefaultPromise@15a2d71
我应该得到一些答案(-561348666),你可以得到
scala> s.find(x => success(Await.result(x,1 seconds))).get onSuccess {case p=> println(p)}
-561348666