与Java内部类相比,Scala闭包 – >最终VS var

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

我实际上正在阅读马丁奥德斯基的Scala书。 似乎Scala简化了很多Java代码,但对于Scala闭包,我注意到了一个显着的差异。

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

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

有人能告诉我为什么马丁奥德斯基,他似乎真正关心function的副作用,选择闭合能够捕获valvar ,而不仅仅是val

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

谢谢

相关问题: 使用Scala闭包,何时捕获的变量开始存在于JVM堆上?

可以看到一个对象可以共享对同一环境的访问,并且该环境通常是可变的。 那么为什么使匿名函数生成的闭包不那么强大呢?

此外,具有可变变量和匿名函数的其他语言也以相同的方式工作。 租赁原则令人惊讶。 Java实际上是WEIRD,不允许内部类捕获可变变量。

有时他们只是非常有用。 例如,自修改thunk以创建自己的惰性或未来处理变体。

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

这里有一些好处和缺点。

在语言设计中有一个原则,即程序员应该明白某些东西的成本。 (我首先在霍尔特的图灵语言的设计和定义中看到了这一点,但我忘记了他给出的名字。)两件看起来相同的东西应该是相同的。 两个当地的vars应该有类似的成本。 这有利于Java。 Java中的两个本地变量实现相同,因此无论是否在内部类中提及其中一个变量,它们的成本相同。 Java最受欢迎的另一点是,在大多数情况下,捕获的变量确实是最终的,因此程序员几乎不需要花费很多成本来捕获非最终的本地变量。 最后的坚持也简化了编译器,因为它意味着所有局部变量都是堆栈变量。

语言设计的另一个原则是正交。 如果可以捕获val,为什么不能使用var。 只要有明智的解释,为什么要加以限制。 当语言不够正确时,它们似乎有悖常理。 另一方面,具有太多正交性的语言可能具有复杂(并且因此有缺陷和/或迟到和/或很少)的实现。 例如,Algol 68在黑桃中具有正交性,但实施它并不容易,这意味着很少实现并且很少采用。 Pascal(大约在同一时间设计)具有各种不优雅的限制,使编写编译器更容易。 结果是大量的实现和大量的采用。

Interesting Posts