Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When to use `constantly` in clojure, how and when are its arguments evaluated?

In the accepted answer to another question, Setting Clojure "constants" at runtime the clojure function constantly is used.

The definition of constantly looks like so:

(defn constantly
  "Returns a function that takes any number of arguments and returns x."
  {:added "1.0"}
  [x] (fn [& args] x))

The doc string says what it does but not why one would use it.

In the answer given in the previous question constantly is used as follows:

(declare version)

(defn -main
  [& args]
 (alter-var-root #'version (constantly (-> ...)))
 (do-stuff))

So the function returned by constantly is directly evaluated for its result. I am confused as to how this is useful. I am probably not understanding how x would be evaluated with and without being wrapped in `constantly'.

When should I use constantly and why is it necessary?

like image 873
Alex Stoddard Avatar asked Oct 25 '10 17:10

Alex Stoddard


1 Answers

The constantly function is useful when an API expects a function and you just want a constant. This is the case in the example provided in the question.

Most of the alter-* functions (including alter-var-root) take a function, to allow the caller to modify something based on its old value. Even if you just want the new value to be 7 (disregarding the old value), you still need to provide a function (providing just 7 will result in an attempt to evaluate it, which will fail). So you have to provide a function that just returns 7. (constantly 7) produces just this function, sparing the effort required to define it.

Edit: As to second part of the question, constantly is an ordinary function, so its argument is evaluated before the constant function is constructed. So (constantly @myref) always returns the value referenced by myref at the time constantly was called, even if it is changed later.

like image 186
Rafał Dowgird Avatar answered Oct 13 '22 20:10

Rafał Dowgird