Search code examples
clojureexpression-evaluation

How does (constantly x) differ from (fn [& _] x)?


I'm using a multimethod to provide different functions depending on what "mode" my project is running in (it's a yada api server, and should be able to run in :dev, :prod modes etc).

I'm using mount/defstate to provide a keyword:

(defstate mode :start :dev)

When I dispatch using (constantly mode), I get errors but when I dispatch using (fn [& _] mode) it seems to work.

Aren't these two forms the same? Or is there some subtle difference in the way in which (or the time at which) they are evaluated?


Solution

  • In mount if you have not started your states yet then their values are DerefableState objects.

    By calling constantly you first evaluate the value of mode and then call the constantly function with the value. This means that when you invoke the result of constantly it will always return the parameter of constantly despite the fact that you have changed it since. If you have not started your state before calling constantly then it will store the DerefableObject.

    On the other hand with (fn [& _] mode) you evaluate the value of the mode var every time you call the function. If you have not started your states then it will also return a DerefableState but if you have then the result will be the expected keyword.

    A simple solution is to put the dispatch function in a state too.

    (defstate dispatch :start (constantly state))