2011-11-10 53 views
7

这个问题纯粹来自“心理主宰”,可能没有实用价值。Clojure编译时​​常量

如果我使用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汇编的内部。

+0

这不是什么形象化。奉献是夸夸其谈或教条主义。 –

+0

是的,我删除它。 – Ralph

回答

11

Clojure 1.3 docs

== 2.14 ^:常量DEFS ==

^:常量可以让你的名字的原始值与基准速度更快。

(DEF常数{:PI 3.14:电子2.71})

(DEF ^:const的PI(:PI常数))(DEF ^:const的E(:电子常量))

的塔顶查找:e和:pi在地图上发生在编译 时间,因为(:pi常量)和(:e常量)在评估它们的 父级def表单时被评估。

5

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

+0

这是一个合理的答案,我在想同样的事情。语法比'〜答案选择更好。 – Ralph

2

`~foo在所有情况下字面上都与foo完全相同 - 无论您认为自己摆脱前者是否是幻想。

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

+0

我没有意识到'〜foo。谢谢。当我更多地考虑这个问题时,'^:const'似乎是正确的方法,但是仅适用于基元**(不包括'String'实例)。字符串的问题是使用宏或const可能会导致运行时比较“字符串”内容而不是地址。如果这样做的理由是为了表现,那是一种损失。 – Ralph