質問

This question comes purely from "mental masterbation" and probably has no practical value.

If I define a value in Clojure using def, can the compiler be induced to evaluate it at compile time, and not wait until run-time?

(def the-answer 42)

(+ the-answer 1)

I guess I could define a macro, but the calling syntax becomes sort of awkward:

(defmacro the-answer [] 42)

(+ (the-answer) 1)

This also works, but is still ugly:

(+ `~the-answer 1)

I also understand (or believe) that Clojure evaluates constant expressions at compile time:

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

I am just learning Common Lisp, but my understanding is that Common Lisp supports user-defined reader macros, so you could define a reader macro (something like #$) that evaluates the following symbol at compile-time:

(+ #$the-answer 1)

By the way, that syntax is no "prettier" than the macro call.

How do I make Clojure evaluate the constant vars at compile time and replace the reference with the actual value? Does it already do so?

Before anyone starts quoting Knuth's Law ("premature optimization is the root of all evil"), I ask this question to better understand the internals of Clojure compilation.

役に立ちましたか?

解決

From the Clojure 1.3 docs

== 2.14 ^:const defs ==

^:const lets you name primitive values with speedier reference.

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

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

The overhead of looking up :e and :pi in the map happens at compile time, as (:pi constants) and (:e constants) are evaluated when their parent def forms are evaluated.

他のヒント

One of the main uses of macroes is moving computation to compile time so it is only done once. With this in mind, my opinion is that macros are the correct tool for this and the extra set of ( ) looks to me like it actually helps make the special parts look special.

`~foo is literally identical to foo in all cases - whatever you think you're getting out of the former is an illusion.

I think :const is probably the right answer, but you can also use symbol-macros from clojure.tools.macro - it has symbol-macrolet and defsymbolmacro/with-symbol-macros for this purpose (as well as other uses).

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top