clojure

Will the clojure compiler automatically evaluate expressions of literals at compile time?


This might be a silly question, but:

Suppose an expression depends only on literals, or on other expressions that also only depend on literals; will the compiler evaluate this at compile time?

Suppose I have,

(def a (some-time-consuming-function some-literal))

(def b (some-other-time-consuming-function a))

Will both b and a be evaluated completely at compile time, so that the User isn't affected?

EDIT: Thanks very much, all of the answers were very helpful.

EDIT 6.6.2011: Turns out that if you try and use this technique to precompute a very large data structure, it's easy to make class files that are too big to load. In those cases you want to create a file which will be read in rather than a class file that will be loaded. The macro tricks described in these answers should only be applied as is in situations where the return value is not a prohibitively large structure.

The error thrown is: "java.lang.ClassFormatError: Invalid this class index" See this thread for discussion of a related situation.


Solution

  • Not silly at all, I had to think about it and test it out.

    It will work only if you use macros instead of functions, since the body of a macro is evaluated at compile/macroexpansion-time. E.g.:

    (defmacro preprocess [f & args]
      (let [x# (apply (resolve f) args)]
        `~x#))
    
    (def a (preprocess some-time-consuming-function some-literal))
    
    (def b (preprocess some-other-time-consuming-function a))
    

    Then a and b are def'd to the values returned from evaluating preprocess.