1

I have the following clojure code to initialize my config structure Config. I noticed that the file is actually read when compiling the file, not at runtime.

For me, the config structure Config should be immutable, however, I do not want to have the configuration inside the JAR file.

How should I do this? Do I have to use an atom? It is okay if the application crashes if my.config is missing.

(def Config
  (read-string (slurp "my.config")))
mattias
  • 870
  • 5
  • 18

3 Answers3

0

When you don't want it at compile time you have to wrap it in a function.

(defn def-my-conf []
  (def Conf (blub)))

But you the cleaner way would be:

(declare Config)

(defn load-Config []
 (alter-var-root (var Config) (blub)))

This function should be called inside your main.

EDIT: Of course an atom is also a solution!

user5187212
  • 426
  • 2
  • 7
  • This solution, and the solution below have both the same problem. I need to edit -main. What options do I have if I do not want to change -main? Anything similar to static constructors in Clojure. I didn't realize that Clojure and ML like Ocaml has such a different definition on when code in a file is executed? In ML, they are executed "while" loading the program, and it is rather often used to collect or prepare global information . – mattias Sep 19 '15 at 15:53
  • See here http://stackoverflow.com/questions/5669933/is-clojure-compiled-or-interpreted – TheQuickBrownFox Sep 19 '15 at 16:14
0

Write a function for reading your config:

(defn read-config
  []
  (read-string
   (slurp "my.config")))

Then you can call this function from -main, and either 1) pass the config on to any functions that will need it, or 2) store it in a dynamic variable and let them read it directly:

(def ^:dynamic *config* nil)

(defn some-function-using-config
  []
  (println *config*))

(defn -main
  []
  (binding [*config* (read-config)]
    (some-function-using-config)))

Which of the two to choose is a matter of taste and situation. With direct passing you make it explicit that a function is receiving config, with the dynamic variable you avoid having to include config as an argument to every single function you write, most of whom will just pass it on.

Both of these solutions work well for unit tests, since you can just rebind the dynamic variable to whatever config you want to use for each test.

bsvingen
  • 2,699
  • 14
  • 18
0

TheQuickBrownFox had the answer, the file is read both at run-time, and a compile-time.

Fine for me! That is actually really cool!

mattias
  • 870
  • 5
  • 18