Dmitry Matveyev
Dmitry Matveyev

Reputation: 481

Environment variables used in `def` statements in Clojure

I have this piece of code:

(def heavy_computation (f1 (env :var1)))

where (env :var1) is fetching environment variable VAR1 (with the help of environ) that points to a directory location and f1 is a wrapper around Java function. This is used later in functions and it is heavy computation that I would like to compute just once.

I want to be able to customize VAR1 and print an error message if it is missing in production.

If I compile this code lein uberjar without environment variables, it throws an error about NullPointerException at this line.

I can compile it with environmental variables and later if I set them appropriately, it will work. In order to print my error message in case it is missing, I have to put the code that checks it right before the def statement, otherwise it throws null pointer exception.

Can I do it in a cleaner way? I don't want to set environment variables in order to compile it and I want to put the code that performs checks in the -main function right before it starts the server.

Upvotes: 4

Views: 647

Answers (2)

Michiel Borkent
Michiel Borkent

Reputation: 34800

Wrap the environment value in an if-let and handle the else branch with printing a warning. During compilation you will see the warning, but that would be OK with me personally. You can also use a memoized function instead of a delay to defer the computation.

Upvotes: 3

Taylor Wood
Taylor Wood

Reputation: 16194

One option is to wrap the evaluation in a delay:

(def heavy-computation (delay (f1 (env :var1))))

Then wherever you need the result, you can deref/@ the delay:

(when (= :ok @heavy-computation)
  (println "heavy!"))

The delay's body will only be evaluated once, and not until you dereference it.

Upvotes: 7

Related Questions