Scala 闭包与 Java 内部类的比较 -> 最终 VS var



我首先问了这个关于在Java中使用匿名内部类的final的问题:为什么我们在匿名内部类中使用final关键字?

实际上,我在读马丁·奥德斯基的《斯卡拉》一书。Scala似乎简化了很多Java代码,但对于Scala闭包,我可以注意到一个显著的区别。

虽然在Java中,我们用一个匿名内部类"模拟"闭包,捕获一个最终变量(它将被复制到堆上而不是堆栈上),但在Scala中,我们似乎可以创建一个闭包,它可以捕获val,也可以捕获var,从而在闭包调用中更新它!

因此,我们可以使用不带final关键字的Java匿名内部类!我还没有读完这本书,但目前我还没有找到足够的关于这种语言设计选择的信息。

有人能告诉我为什么Martin Odersky,他似乎真的很关心函数的副作用,选择闭包来同时捕获valvar,而不仅仅捕获val吗?

Java和Scala实现的优点和缺点是什么?

感谢

相关问题:有了Scala闭包,捕获的变量什么时候开始在JVM堆中存在?

一个对象可以看作是一袋闭包,它们共享对同一环境的访问权限,并且该环境通常是可变的。那么,为什么要降低匿名函数生成的闭包的功能呢?

此外,其他具有可变变量和匿名函数的语言也以同样的方式工作。租赁惊奇原则。Java实际上很奇怪,它不允许内部类捕获可变变量。

有时它们非常有用。例如,一个自我修改的thunk来创建自己的懒惰或未来处理变体。

不利因素?它们具有共享可变状态的所有缺点。

以下是一些优点和缺点。

在语言设计中有一个原则,即某些东西的成本对程序员来说应该是显而易见的。(我第一次看到这一点是在霍尔特的《图灵语言的设计与定义》中,但我忘记了他给它起的名字。)两个看起来一样的东西应该是一样的。两个本地vars的成本应该相似。这对Java有利。Java中的两个本地变量实现相同,因此无论内部类中是否提到其中一个,成本都相同。Java支持的另一点是,在大多数情况下,捕获的变量确实是最终变量,因此程序员捕获非最终本地变量几乎没有成本。此外,对final的坚持简化了编译器,因为这意味着所有的局部变量都是堆栈变量。

语言设计的另一个原则是正交的。如果可以捕获val,为什么不能捕获var。只要有合理的解释,为什么要限制。当语言不够正交时,它们似乎是反常的。另一方面,具有太多正交性的语言可能具有复杂的实现(因此存在缺陷和/或延迟和/或很少)。例如,Algol 68在spades上具有正交性,但实现它并不容易,这意味着实现很少,吸收也很少。Pascal(大约在同一时间设计)有各种不雅的限制,这使得编写编译器变得更容易。结果是大量的实现和大量的吸收。

最新更新