Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala 意外的Future.map()执行顺序_Scala - Fatal编程技术网

Scala 意外的Future.map()执行顺序

Scala 意外的Future.map()执行顺序,scala,Scala,我有以下Scala程序: object FutureMapTest extends App { println("start") val f: Future[Long] = Future { Thread.sleep(2000) val x = 1 println(s"started with ${x}") x } f.map { i => println(s"mapped to ${i*2}") }

我有以下Scala程序:

object FutureMapTest extends App {
   println("start")

   val f: Future[Long] = Future {
     Thread.sleep(2000)
     val x = 1
     println(s"started with ${x}")
     x
   }
   f.map { i =>
     println(s"mapped to ${i*2}")
   }
   f.map {
     val nothing = "nothing"
     println(s"mapped to ${nothing}")
     _ * 2
   }

   Thread.sleep(3000)
   println("end")
}
我希望它在控制台上打印的是

start
started with 1
后跟(以任何顺序):

end
它实际打印的是:

start
mapped to nothing
started with 1
mapped to 2
end
因此,第二个“映射”块似乎可以立即执行,而不必等待最初的未来完成。这怎么可能


您甚至可以从原来的future块中删除Thread.sleep(),结果仍然是一样的。

这里有几个混淆的来源

这:

扩展到:

f.map {
  val nothing = "nothing"
  println(s"mapped to ${nothing}")
  i => i * 2
}
这是什么意思
Future#map
对于某些
Future[a]
,需要一个a
a=>B
的函数参数。表达方式:

val nothing = "nothing"
println(s"mapped to ${nothing}")
i => i * 2
..的计算结果为
Long=>Long
,但val赋值和
println
是首先计算的,因为它们是返回函数的表达式的一部分
i=>i*2
f
完成之前不会执行。这类似于():

将其更改为此将显示您期望的行为(现在val赋值和
println
是函数体的一部分):

下面是另一种看待它的方式:

f.map {
  println("evaluated immediately")
  i => { println("evaluated after f"); i * 2 }
}

这里有几个令人困惑的地方

这:

扩展到:

f.map {
  val nothing = "nothing"
  println(s"mapped to ${nothing}")
  i => i * 2
}
这是什么意思
Future#map
对于某些
Future[a]
,需要一个a
a=>B
的函数参数。表达方式:

val nothing = "nothing"
println(s"mapped to ${nothing}")
i => i * 2
..的计算结果为
Long=>Long
,但val赋值和
println
是首先计算的,因为它们是返回函数的表达式的一部分
i=>i*2
f
完成之前不会执行。这类似于():

将其更改为此将显示您期望的行为(现在val赋值和
println
是函数体的一部分):

下面是另一种看待它的方式:

f.map {
  println("evaluated immediately")
  i => { println("evaluated after f"); i * 2 }
}
另一个困惑是,在没有更多担保的情况下,“结束”必须排在最后。另一个困惑是,在没有更多担保的情况下,“结束”必须排在最后。
f.map {
  println("evaluated immediately")
  i => { println("evaluated after f"); i * 2 }
}