2014年7月28日
for
与await的冲突
Scala提议标准scala.async
有个缺陷:不支持for
循环1。比如,类似这样的代码无法编译:
import scala.async.Async._
val xs = Seq(1, 2, 3)
async {
for (x <- xs) {
await(async(x * 2)) // 编译错误
}
}
我们的Stateless Future也存在类似的问题,以下代码也不能编译:
import com.qifun.statelessFuture.Future
val xs = Seq(1, 2, 3)
Future {
for (x <- xs) {
Future(x * 2).await // 编译错误
}
}
冲突的原因
这是因为,Scala语言的for
语句会被转换成foreach
、map
、flatMap
、withFilter
函数调用。而for
的内部语句块会转换成一个函数对象。比如上述代码相当于
import com.qifun.statelessFuture.Future
val xs = Seq(1, 2, 3)
Future {
xs.map { x =>
Future(x * x).await // 编译错误
}
}
由于上述代码中的await位于匿名函数{ x => ... }
中,所以await
与外层Future
的关联就会阻断,最终导致编译错误。
futureSeq包装函数
幸好,Stateless Future的工具库中,有个futureSeq函数可以解决await与for
的冲突。只要给xs
包装一层futureSeq就可以了。
import com.qifun.statelessFuture.Future
import com.qifun.statelessFuture.util.AwaitableSeq.futureSeq
val xs = Seq(1, 2, 3)
Future {
val xs2 = for (x <- futureSeq(xs)) {
Future(x * x).await // 编译通过
}
}
futureSeq 也支持for
/yield
推导式:
import com.qifun.statelessFuture.Future
import com.qifun.statelessFuture.util.AwaitableSeq.futureSeq
val xs = Seq(1, 2, 3)
Future {
val xs2 = for (x <- futureSeq(xs)) yield {
Future(x * x).await // 编译通过
}
}
(待续)
-
Github上的相关问题讨论:scala/async#32 ↩
- 栏目
- 程序设计 (7)