我对Scala期货所观察到的事情感到困惑,我无法弄清楚这里会发生什么。我将未来映射到另一个结果,没有什么花哨的:
import scala.concurrent.{Await, Future}
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration._
object Example extends App {
val f = Future {
Thread.sleep(1000)
println("Future: " + Thread.currentThread + " (" +
System.currentTimeMillis + ")")
"future"
}
val g = f map { x =>
println("Map future: " + Thread.currentThread +
" (" + System.currentTimeMillis + ")")
"mapped " + x
}
println(Await.result(g, 5 seconds))
}
由于我将未来映射到的函数取决于f
的结果,我希望该函数仅在f
的计算完成后触发。这也是我用上面的代码可以观察到的。但是,当我更改g
的函数以携带匿名参数时,此行为会更改:
val g = f map {
println("Map future: " + Thread.currentThread + " (" +
System.currentTimeMillis + ")")
"mapped " + _
}
即使g
的结果取决于f
的结果,也会在f
的计算完成之前触发该方法。看起来好像该方法在实际需要输入值之前和之后被拆分为一部分。此外,线程的第一部分在main中执行。这是编译器在这里做的事吗?对我来说,这非常出乎意料。或者这种行为是否在Scala的某处表达过?但是我无法在消息来源中找到它。
有人知道这里发生了什么吗?我正在使用Scala 2.10。
答案 0 :(得分:10)
它可能会让你感到惊讶,但是在lambda构建期间执行println:
List(1,2,3).map {
println("Hi!")
"Processing " + _
}
// Hi!
// res4: List[String] = List(Processing 1, Processing 2, Processing 3)
正如您所看到的,Hi!
只被输出一次。
这是因为您的代码在语义上与:
相同def constructLambda() = {
// do something, e.g. println
// now return actual lambda
}
val lambda = constructLambda()
xs map (lambda) // now trigger previously *lazy* piece of code
// or even this, like in your snippet
xs map lambda