【发布时间】:2011-03-17 15:11:00
【问题描述】:
我正在编写一些依赖于许多常量的 Clojure 代码。
它们将在紧密的内部循环中使用,因此通过 Clojure 编译器+JVM 组合尽可能高效地使用和优化它们很重要。出于同样的目的,我通常会在 Java 中使用“public static final”常量。
声明这些的最佳方式是什么?
【问题讨论】:
标签: java performance optimization clojure constants
我正在编写一些依赖于许多常量的 Clojure 代码。
它们将在紧密的内部循环中使用,因此通过 Clojure 编译器+JVM 组合尽可能高效地使用和优化它们很重要。出于同样的目的,我通常会在 Java 中使用“public static final”常量。
声明这些的最佳方式是什么?
【问题讨论】:
标签: java performance optimization clojure constants
我认为def-ing 全局命名空间中的东西已经尽可能接近了。
【讨论】:
我相信 Clojure 1.3(或者可能是 1.4)允许您在 def 上放置 ^:constant 标签,向编译器表明这应该是一个常量,并且所有引用都应该在编译时解析。
显然它是 Clojure 1.3,它是 ^:const,而不是 ^:constant。有关摘要,请参阅 How does Clojure ^:const work?。
【讨论】:
没有defconst,所以只使用全局定义是惯用的;就优化而言,JIT 会让事情变得更快。
【讨论】:
如果真的、真的、真的想要常量(我相信,JIT 会注意到该值是常量并做正确的事情),您可以使用宏。
(defmacro my-constant [] 5)
这是相当丑陋的,但性能关键的代码总是很丑陋,我猜。
(do-stuff (my-constant) in-place)
不过,请注意您放入宏的内容!除了一些文字常量外,我不会这样做。尤其不是对象。
【讨论】:
如果仅使用def 不够快,您可以尝试在进入紧密循环之前创建一个let 绑定别名以避免每次都经过一个var。
【讨论】:
如上所述,使用 def 或 atom,请记住,数据是不可变的,因此如果您在列表中声明一些常量,它们不会改变。
【讨论】: