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

ffr*_*end 14 performance clojure let

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

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

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

mik*_*era 17

let-bound变量作为最终本地值存储在堆栈中.

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

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