gpt4 book ai didi

scala - 当定义闭包时,Scala 如何维护变量的值?

转载 作者:行者123 更新时间:2023-12-02 08:49:03 26 4
gpt4 key购买 nike

scala 是通过复制还是引用来维护变量的值?

例如,在 Ruby 中,“闭包实际上会延长它需要的所有变量的生命周期。它不会复制它们,但会保留对它们的引用,并且变量本身将不符合垃圾回收的条件(如果该语言有垃圾收集),而闭包即将到来”。 [斯科金]

最佳答案

jvm 没有闭包,它只有对象。 scala 编译器生成匿名类,为代码中每次出现的闭包实现适当的 Function 特征(取决于签名的参数和结果类型)。

例如,如果对于某些l : List[Int],您编写l.map(i => i + 1),它将被转换为

class SomeFreshName extends Function[Int, Int] {
def apply(i: Int) = i + 1
}

l.map(new SomeFreshName())

在这种情况下,不存在真正的闭包,就像 i => i + 1 中一样,没有自由变量,只有参数 i 和常量。

如果你关闭了一些局部值,或者相​​当于函数的参数,它们必须作为构造函数参数传递给闭包实现类:

for l.map(i => s + i) 其中 s 是字符串参数或方法的本地参数,它会这样做

class SomeFreshName(s: String) extends Function[Int, String] {
def apply(i: Int) = s + i
}
l.map(new SomeFreshName(s))

根据需要在构造函数中传递尽可能多的参数。

注意:如果 s 是类的字段而不是方法的本地字段,则 s + i 实际上将是 this.s + i,并且this 将被传递给匿名类。

垃圾收集器中没有什么特别的(同样,jvm 不知道闭包),简单地说,由于闭包对象具有对 s 的引用,因此 s 的生存时间至少与闭包对象一样长。

请注意,在具有匿名类的 java 语言中,也会发生完全相同的情况。当匿名类使用封闭方法的局部变量时,这些局部变量会默默地添加为匿名类的字段,并在构造函数中传递。

在 java 中,只有当局部变量是 final 时才允许这样做,这相当于 scala val,而不是 var

事实上,通过这个实现,一旦创建了闭包,它就拥有了它自己的关闭其他变量的副本。如果修改它们,这些修改将不会反射(reflect)在方法中。如果它们在闭包中被修改,则不会反射(reflect)在方法中。

假设你写

var i = 0
l.foreach{a => println(i + ": " + a); i = i + 1}
println("There are " + i + " elements in the list")

之前描述的实现是

class SomeFreshName(var i: Int) extends Int => Unit {
def apply(a: Int) = println(i + ": " + a); i = i + 1
}
var i = 0
l.foreach(new SomeFreshName(i)
println("There are " + i + " elements in the list")

这样做,就会有两个变量 i,一个在方法中,一个在 SomeFreshName 中。只有 SomeFreshName 中的那个会被修改,最后一个 println 总是报告 0 个元素。

Scala 通过用引用对象替换闭包中的 var 来解决他的问题。给定一个类

class Ref[A](var content: A)

代码首先替换为

val iRef = new Ref[Int](0)
l.foreach{a =>
println(iRef.content + ": " + a);
iRef.content += iRef.content + 1
}
println("There are " + i + " elements in the list")

当然,这仅针对恰好被闭包获取的 var 执行,而不是针对每个 var。这样做,var 已被 val 替换,实际变量值已移至堆中。现在,关闭可以像往常一样完成,并且有效

class SomeFreshName(iRef: Ref[Int]) ...

关于scala - 当定义闭包时,Scala 如何维护变量的值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11657676/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com