Clojure编译时​​常量

时间:2011-11-10 12:38:59

标签: clojure compile-time-constant

这个问题纯粹来自“心理大师”,可能没有实际价值。

如果我使用def在Clojure中定义一个值,是否可以诱导编译器在编译时对其进行评估,而不是等到运行时?

(def the-answer 42)

(+ the-answer 1)

我想我可以定义一个宏,但调用语法变得有些尴尬:

(defmacro the-answer [] 42)

(+ (the-answer) 1)

这也有效,但仍然很难看:

(+ `~the-answer 1)

我也理解(或相信)Clojure在编译时评估常量表达式:

(def milliseconds-per-day (* 24 60 60 1000))

我只是在学习Common Lisp,但我的理解是Common Lisp支持用户定义的阅读器宏,因此您可以定义一个阅读器宏(类似#$),在编译时评估以下符号:

(+ #$the-answer 1)

顺便说一句,这种语法并不比宏调用更“漂亮”。

如何让Clojure在编译时评估常量变量并用实际值替换引用?它已经这样做了吗?

在任何人开始引用Knuth定律之前(“过早优化是所有邪恶的根源”),我要求这个问题更好地理解Clojure编译的内部。

3 个答案:

答案 0 :(得分:11)

来自Clojure 1.3 docs

  

== 2.14 ^:const defs ==

     

^:const允许您使用更快的参考命名原始值。

     

(def constants {:pi 3.14:e 2.71})

     

(def ^:const pi(:pi constants))(def ^:const e(:e constants))

     

查找的开销:e和:地图中的pi发生在编译时   时间,因为(:pi常数)和(:e常数)在它们的时候进行评估   父母def表格被评估。

答案 1 :(得分:5)

macroes的一个主要用途是将计算转移到编译时间,因此只执行一次。考虑到这一点,我的意见是宏是这个的正确工具,额外的( )看起来像它实际上有助于使特殊部分看起来特别。

答案 2 :(得分:2)

`~foo在所有情况下都与foo完全相同 - 无论你认为你从前者中脱离出来都是一种错觉。

我认为:const可能是正确答案,但你也可以使用clojure.tools.macro中的符号宏 - 它有symbol-macroletdefsymbolmacro / with-symbol-macros为此目的(以及其他用途)。