让我们看一些例子。
scala> import scala.util.Random
import scala.util.Random
scala> :paste
// Entering paste mode (ctrl-D to finish)
Seq(1, 2, 3).map {
val rand = new Random().nextInt
_ + rand
}
// Exiting paste mode, now interpreting.
res0: Seq[Int] = List(-921709014, -921709013, -921709012)
scala> :paste
// Entering paste mode (ctrl-D to finish)
Seq(1, 2, 3).map {
_ + new Random().nextInt
}
// Exiting paste mode, now interpreting.
res1: Seq[Int] = List(-884268781, 516035717, -2054776549)
scala> :paste
// Entering paste mode (ctrl-D to finish)
Seq(1, 2, 3).map { i =>
val rand = new Random().nextInt
i + rand
}
// Exiting paste mode, now interpreting.
res2: Seq[Int] = List(-1258337635, 1817183115, -1994392)
此处,res0
的值被添加到相同的随机号中,表明生成了相同的随机数三次(极不可能)或者只生成了一个随机数。 res1
看起来像预期的那样告诉我们直接函数调用而没有按预期分配val
生成的随机数。最后,res2
也看起来是正确的,唯一的区别是使用了变量而不是使用_
。
我很难理解为什么res0
和res2
行为不同。特别是,为什么res0
没有像预期的那样表现出来。
答案 0 :(得分:3)
第一个:
Seq(1, 2, 3).map {
val rand = new Random().nextInt
_ + rand
}
相当于:
// nextInt is outside the body of the function given to map
Seq(1, 2, 3).map({
val rand = new Random().nextInt // nextInt evaluated once here (before map)
i => i + rand // only this function given to map
})
第二个:
Seq(1, 2, 3).map {
_ + new Random().nextInt
}
相当于:
// nextInt is inside the body given to map
Seq(1, 2, 3).map {
i => i + new Random().nextInt
}
答案 1 :(得分:3)
鉴于你的代码:
Seq(1, 2, 3).map {
val rand = new Random().nextInt
_ + rand
}
可以重写为:
Seq(1, 2, 3).map({
val rand = new Random().nextInt
x => x + rand
})
您可以在此处看到,值rand
未在实际函数定义x => x + rand
中计算。 在中从定义函数的上下文中关闭。所以基本上它是一个闭包。因此,只要评估函数x => x + rand
,就会重新使用先前计算的rand
值。
有关详细信息,请查看 Scala中的编程一书中的Functions and Closures(8.7个闭包)一章。