Scala 从 Try 到 Future 的隐式转换

标签 scala for-loop future implicit-conversion implicit

我试图在 Scala 的 for 循环中将 TryFuture 混合,而不显式转换 Try s 到 Futures 与 Future.fromTry。看起来它在某些情况下会自动工作,但在其他情况下则不会。

以下代码片段失败并显示

import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent._
import scala.util._

for {
  a <- Try(5)
  b <- Future(10)
} yield { a + b } 

type mismatch;
found : scala.concurrent.Future[Int]
required: scala.util.Try[?]
b <- Future { 10 }
^
Compilation Failed

另一方面,如果我删除关键字yield,它就会起作用:

import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent._
import scala.util._

for {
  a <- Try(5)
  b <- Future(10)
} { println(a + b) }

当我将 for 循环重写为嵌套的 foreachmap 时,它也可以工作:

@ Try(5) foreach { a => Future(10) foreach { b => println(a + b) } }
15


@ Try(5) map { a => Future(10) map { b => a + b } }
res5: Try[Future[Int]] = Success(Future(Success(15)))

有人可以解释一下为什么会发生这种情况吗?这是一个错误吗?或者我错过了什么?

ps。 Scala 2.11 和 2.12 中的行为相同。

最佳答案

foreach 返回一个 Unit 类型;因此是“常见”类型。

如果没有 yield 关键字,编译器会将您的 for 理解解释为:

Try(5).foreach(a => Future(10).foreach(b => println(a + b)))

只要将 FutureTry (两个不同的 monad)链接到 foreach 周围,就可以处理它们。

如果您添加 yield 关键字,编译器将使用 flatMap/map 解释您的 for 理解;如下:

Try(5).flatMap(a => Future(10).map(b => a + b))

Try#flatMap 期望一个具有 Try 作为返回类型的函数,但它得到一个 Future,使得整个无法编译。

TL;DR:foreach 不希望在链接期间匹配函数类型,因为它在所有情况下都返回 Unit;这就是它编译的原因。

请注意以下事项:

Try(5) map { a => Future(10) map { b => a + b } }

可以工作,因为map不需要展平类型;所以包装编译具有独特的“效果”。 展平不同的类型会使编译器失败;正如 flatMap 尝试做的那样。

关于Scala 从 Try 到 Future 的隐式转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49842751/

相关文章:

c++ - 如何在没有竞争条件的情况下将 QFutureWatcher 与 QtConcurrent::run() 一起使用

dart - Future.then返回意外的空值

scala - 使用 Scala 的 Iterator++ (concat) 递归堆栈安全吗?

scala - 我可以使用绑定(bind)在 Scala 值类中的 View 吗?

java - android scala eclipse 插件的 searchView 小部件中的过滤方法

javascript - 为什么我不能遍历字典/键数组

php - 简单的for循环不起作用

rust - 在 actix-web 中处理异步处理程序中的错误最惯用的方法是什么?

http - 在 Lift RestHelper 中获取 currentUser

PHP 是否可以跳过两次或多次迭代?