Scala关闭词法范围

时间:2016-12-15 12:36:47

标签: scala closures 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中关闭不要深层复制对象,它们只是保持对象的引用。究竟是什么意思

1 个答案:

答案 0 :(得分:1)

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

val d = c

c和d都包含相同的参考。但是当你写道:

c = new Cell(10)

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

使用REPL可以更容易地看到这一点,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引用的类时,它也会更新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仍然有相同的参考(为什么不呢?)。