Clojure def vs defn for a function with no arguments

Clojure

Clojure Problem Overview


I have written a program in clojure but some of the functions have no arguments. What would be the advantages of coding such functions as a "def" instead of a "defn" with no arguments?

Clojure Solutions


Solution 1 - Clojure

(def t0 (System/currentTimeMillis))
(defn t1 [] (System/currentTimeMillis))
(t1)
;; => 1318408717941
t0
;; => 1318408644243
t0
;; => 1318408644243
(t1)
;; => 1318408719361

Solution 2 - Clojure

defs are evaluated only once whereas defns (with or without arguments) are evaluated (executed) every time they are called. So if your functions always return the same value, you can change them to defs but not otherwise.

Solution 3 - Clojure

(defn name ...) is just a macro that turns into (def name (fn ...) anyway, not matter how many parameters it has. So it's just a shortcut. See (doc defn) for details.

https://clojure.org/guides/learn/functions#_defn_vs_fn

Solution 4 - Clojure

The def special form creates a Var object identified by a symbol given as its first argument. Identification is created by associating the given symbol with a Var in a map called namespace.

The Var holds a reference to some value, which could be expressed (among others):

  • as a constant form, which always evaluates to its own value:
(def x 1)
x
;; => 1             ; x holds a reference to a number 1
  • as a function form, which at first is evaluated to its resulting value:
(def x (+ 2 2))
x
;; => 4             ; x holds a reference to a number 4
  • as a Java method form, which at first is evaluated to its resulting value:
(def x (System/currentTimeMillis))
x
;; => 1417811438904 ; x holds a reference to a number 1417811438904
x
;; => 1417811438904 ; still the same number!
  • as a lambda form (anonymous function), which at first is evaluated to a function object:
(def x (fn [] (System/currentTimeMillis)))
x
;; => #<user$x user$x@4c2b1826>
(x)                             ; function form, function evaluated
;; => 1417811438904
(x)                             ; function form, function evaluated
;; => 1417812565866

There is a simple rule for all of the above. In case of def special form an S-expression given as its second argument is recursively evaluated before binding is created, so the resulting Var is bound to the result of this evaluation.

Even fn is evaluated before, but its resulting value is a function object that holds a code. This code will be executed (and evaluated) each time the function is called. That's why there are different results.

The defn macro is just like def but internally it creates an anonymous function and then binds a Var object to it. Its second argument becomes a body of this function and it's not evaluated in a "regular" way. One could also say it is evaluated but as a lambda form – the result of the evaluation is a function object, not the result of some instant calculation.

So writing:

(defn fun [] 1)

Is synonymous to:

(def fun (fn [] 1))

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionyazz.comView Question on Stackoverflow
Solution 1 - ClojurejamesqiuView Answer on Stackoverflow
Solution 2 - ClojureAbhinav SarkarView Answer on Stackoverflow
Solution 3 - ClojureRoman BataevView Answer on Stackoverflow
Solution 4 - ClojuresiefcaView Answer on Stackoverflow