Scala 闭包词法作用域

Scala closure Lexical Scope

 class Cell(var x: Int)
  var c = new Cell(1)

  val f1 = () => c.x /* Create a closure that uses c */

  def foo(e: Cell) = () => e.x /* foo is a closure generator with its own scope */

 // f2 wont do any reference/deep copy
  val f2 = foo(c) /* Create another closure that uses c */

  val d = c  /* Alias c as d */
  c = new Cell(10) /* Let c point to a new object */
  d.x = d.x + 1 /* Increase d.x (i.e., the former c.x) */

  // now c.x refers to 10
  println(f1()) /* Prints 10 */
  println(f2()) /* Prints 2 */

这里 f2() 打印 2 ,因为 scala 不会进行深度复制,为什么值仍然保留为 1,它应该是 10.. 我哪里错了

2) 我读过 smomehere,scala 中的闭包不深复制对象,它们只是保留对对象的引用。这到底是什么意思

由于您复制它的方式,您的示例有点难以理解(创建 Cell 时看起来所有代码都是 运行,但如果这是真的,您将获得无限递归). f1 和 f2 return 不同结果的原因是它们指向不同的单元格。你是对的,当你写:

val d = c

c 和 d 都包含相同的引用。但是当你写:

c = new Cell(10)

c 现在是对新单元格的引用,d 不会复制该引用。

使用 REPL 更容易看到这一点,它可以打印十六进制引用位置。

scala> class Cell(var x: Int)
defined class Cell

scala> var a = new Cell(5)
a: Cell = Cell@368239c8

scala> val b = a
b: Cell = Cell@368239c8

我们可以看到 a 和 b 包含对同一单元格的引用。

scala> a.x = 10
a.x: Int = 10

scala> b.x
res0: Int = 10

当我们更新 a 引用的 class 时,它也会为 b 更新。

scala> a = new Cell(7)
a: Cell = Cell@5b87ed94

scala> b
res1: Cell = Cell@368239c8

scala> a.x
res2: Int = 7

scala> b.x
res3: Int = 10

当我们将变量 a 分配给新单元格时,它具有不同的引用位置(它是 Cell 的不同实例)。 b 仍然具有相同的引用(为什么不呢?)。