Scala 有连续的未来吗?
我有一些副作用Scala 有连续的未来吗?,scala,stream,functional-programming,future,sequential,Scala,Stream,Functional Programming,Future,Sequential,我有一些副作用 def f(): Future[Int] = { val n = Random.nextInt() println(s"Generated $n") Future(n) } 我想重复执行它,直到谓词返回true def success(n: Int): Boolean = n % 2 == 0 scala> Future.find(s)(success) map println Generated -237492703 Generated -93547629
def f(): Future[Int] = {
val n = Random.nextInt()
println(s"Generated $n")
Future(n)
}
我想重复执行它,直到谓词返回true
def success(n: Int): Boolean = n % 2 == 0
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)
我的计划是建立结果流
val s = Stream.fill(10)(f)
然后使用Future.find
获得满足谓词的第一个结果
Future.find(s)(success) map println
问题是Future.find
并行运行所有期货,我希望它依次执行期货,直到谓词返回true为止
def success(n: Int): Boolean = n % 2 == 0
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为止?标准库或第三方库中是否有合适的函数?首先,让我们让我们不感兴趣的未来失败:
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))
如果我理解了这个问题,那么您必须阻塞线程才能继续。您可以使用wait来实现这一点
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
我建议使用另一种方法,而不是使用流。以递归方式使用Future的筛选器和recoverWith:
def findFirst[A](futureGen: => Future[A], predicate: A => Boolean): Future[A] = {
futureGen.filter(predicate).recoverWith { case _ => findFirst(futureGen, predicate) }
}
findFirst(f, success)
这将一个接一个地呼唤未来,直到“成功”回归现实
foldLeft
执行所有期货,但我希望执行足够的期货来满足谓词。@lambdas Oops。当然你是对的,你需要一个懒散的右折叠。编辑。再编辑一次,因为匹配流的模式不够懒。谢谢你的努力!我仍然认为使用标准库、scalaz、twitter futures或其他我不知道的东西,有一种更简单的方法来解决这个问题。哦,scalaz确实包含了惰性右折叠,称为foldr
。我认为在我的原始解决方案中,用foldr
替换foldLeft
应该是可行的,模参数顺序。另请参见“我想获得Future[Option[Int]]”的答案,可以将最后一个表达式包装在Future{…}
中吗<代码>未来与等待
在一起,看起来很奇怪;)我不知道你要怎么用它。您可以包装表达式,但它可能正确,也可能不正确,这取决于您的用例。s、 find(x=>success(wait.result(x,1秒)).get返回未来[Int]您可以查看std-lib案例的scalaz-stream
或iteratee
replicate。看起来像是我当前使用的手工递归,除了过滤器
和recoverWith
:)好吧。。。有时候你应该坚持简单的解决方案。