如何在Clojure中实现`let`以及它的开销是多少?

时间:2012-05-16 02:58:25

标签: performance clojure let

我可以看到实现let绑定的两种方法。首先,从SICP可知,let可以实现为 lambda函数。这是方便和简单的,但考虑到每个lambda(fn)在JVM中被转换为单独的类并且在平均程序中使用let的次数的事实,这看起来非常非常昂贵。

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

那么Clojure中使用的实际实现是什么?指出Clojure源中的相应行是值得赞赏的。

2 个答案:

答案 0 :(得分:17)

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

因为它们是最终的,所以如果需要它们可以绑定到闭包中(这类似于如何在Java中使用匿名内部类中的最终局部变量)。在引擎盖下,JVM将值复制到表示闭包的对象中(将其存储为最终字段)。因此,即使在堆叠框架消失后,闭合仍然有效。

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

答案 1 :(得分:1)

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