14

我可以看到两种实现let绑定的方法。首先,从SICP 可知let可以实现为lambda 函数。这很方便和简单,但考虑到每个 lambda( fn) 在 JVM 中被翻译成单独的类以及let在普通程序中使用的次数,这似乎非常非常昂贵。

其次,let绑定可以直接转换为本地 Java 变量。这几乎没有开销,但是将绑定存储在堆栈上会破坏语言语义:在这种情况下,创建闭包是不可能的 - 保存的值将在堆栈展开后立即被销毁。

那么 Clojure 中使用的实际实现是什么?指向 Clojure 源代码中的相应行表示赞赏。

4

2 回答 2

17

let绑定变量作为最终本地值存储在堆栈中。

由于它们是最终的,因此可以在需要时将它们绑定到闭包中(这类似于在 Java 的匿名内部类中使用最终局部变量的方式)。在底层,JVM 将值复制到代表闭包的对象中(它被存储为最终字段)。结果,即使在堆栈帧消失后,闭包仍然有效。

总体而言,let-bound 变量的开销极低,从性能角度来看,您应该毫不犹豫地使用它们。在 JVM 上可能无法做得更好。

于 2012-05-16T03:02:12.230 回答
1

局部变量是指针,分配在堆栈上,指向堆上的值/对象。指针超出范围,但只要闭包保留指向它的指针,对象就会保持活动状态。

于 2012-05-16T19:22:32.307 回答