*compile-files* is a Clojure dynamic variable that is true while compilation is in progress. The standard-library function compile establishes this binding; ordinary REPL evaluation normally sees it as false. section 23.6 section 15.3
Use it to guard expressions whose evaluation is unsafe or environment-specific during ahead-of-time compilation. A form inside (when-not *compile-files* ...) runs during normal loading but is skipped while compiling. section 23.6
Avoiding compile-time environment capture
A hosts list read from /etc/hosts would otherwise be initialized on the compiling machine. Wrapping the initialization with (when-not *compile-files* ...) defers it until runtime. A macro can package this pattern: (defmacro defruntime [sym & body] `(defonce ~sym (when-not *compile-files* ~@body))). section 23.6
Compilation-sensitive behavior appears in several practical forms:
- Combine *compile-files* with *compile-path* and eval to compile an arbitrary form, write its generated class to disk, and evaluate its result. section 23.7
- Use it with *file* and *source-path* to identify compilation context; unbound contexts report NO_SOURCE_PATH. section 23.9
- Recognize that gen-class depends on compilation context: evaluating it in a REPL does not generate the class, whereas compiling a file containing it does. section 15.3
(require '[clojure.java.io :as io])
(require '[clojure.string :as string])
(defonce hosts ; #1
(with-open [r (io/reader "/etc/hosts")]
(println "Loaded hosts")
(->> r
line-seq
(map #(string/split % #"\t")) ; #2
(filter (comp #{"127.0.0.1"} first)) ; #3
(remove (comp #{"localhost"} last)) ; #4
(map last)
doall)))
(defn allow? [domain] ; #5
(not (some (partial re-find domain) hosts)))
(allow? #"reddit") ; #6
;; false
Inspect a complete runtime-only initialization example that reads and filters /etc/hosts, then queries the resulting data. section 23.6
