在Scala中输入以下小的顺序程序及其并行版本:
/* Activate time measurement in "App" class. Prints [total <X> ms] on exit. */
util.Properties.setProp("scala.time", "true")
/* Define sequential program version. */
object X extends App { for (x <- (1 to 10)) {Thread.sleep(1000);println(x)}}
/* Define parallel program version. Note '.par' selector on Range here. */
object Y extends App { for (y <- (1 to 10).par) {Thread.sleep(1000);println(y)}}使用X.main(Array.empty)执行X会给出:
1
2
3
4
5
6
7
8
9
10
[total 10002ms]而Y与Y.main(Array.empty)给出:
1
6
2
7
3
8
4
9
10
5
[total 5002ms]到目前一切尚好。但是,程序的以下两个变体又如何呢?
object X extends App {(1 to 10).foreach{Thread.sleep(1000);println(_)}}
object Y extends App {(1 to 10).par.foreach{Thread.sleep(1000);println(_)}}分别给我[total 1002ms]和[total 1002ms]的运行时。,这怎么可能?
发布于 2011-09-18 16:27:15
这与并行集合无关。这个问题隐藏在函数文字中。如果让编译器显示AST (带有选项-Xprint:typer),您可以看到它:
for (x <- (1 to 10)) {Thread.sleep(1000);println(x)}产生
scala.this.Predef.intWrapper(1).to(10).foreach[Unit](((x: Int) => {
java.this.lang.Thread.sleep(1000L);
scala.this.Predef.println(x)
}))鉴于
(1 to 10).foreach{Thread.sleep(1000);println(_)}产生
scala.this.Predef.intWrapper(1).to(10).foreach[Unit]({
java.this.lang.Thread.sleep(1000L);
((x$1: Int) => scala.this.Predef.println(x$1))
})有一点不同。如果希望得到预期的结果,则必须将foreach-表达式更改为
(1 to 10).foreach{x => Thread.sleep(1000);println(x)}但有什么不同呢?在您的代码中,您向foreach声明一个块,在执行该块之后,它将返回要执行的函数。然后将返回的函数传递给foreach,而不是包含它的块。
这个错误是经常犯的。它与下划线文字有关。也许this question能帮你。
发布于 2014-01-02 22:38:09
一种有趣的思考方法是,因为scala是按值调用(Call by name vs call by value in Scala, clarification needed),当您传递{Thread.sleep(1000);println()}以预先计算块{Thread.sleep(1000);println()}时,只需将生成的println(_)函数传递一次。当您执行foreach(x => Thread.sleep(1000);println(x))时,您将Thread.sleep(1000)和println(x)传递到函数foreach中。这只是另一种表达sschaef已经说过的话的方式。
https://stackoverflow.com/questions/7461942
复制相似问题