这个问题纯粹来自“心理大师”,可能没有实际价值。
如果我使用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 :(得分:11)
== 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-macrolet
和defsymbolmacro
/ with-symbol-macros
为此目的(以及其他用途)。