While studying Clojure and trying to understand closures, I wrote the following code snippets:
(defn calculate-how-to-end-sentence  (Thread/sleep 3000) ; just for test (str "!"))
(defn create-greeting-function1 [greeting] (fn [person-name] (str greeting " " person-name (calculate-how-to-end-sentence)))) (def greeting-friend1 (create-greeting-function1 "Hi")) (def greeting-neighbour1 (create-greeting-function1 "Hello")) (greeting-friend1 "Tom") ; "Hi Tom!" (greeting-neighbour1 "Nancy") ; "Hello Nancy!"
(defn create-greeting-function2 [greeting] (let [end-of-line (calculate-something-that-takes-time)] (fn [person-name] (str greeting " " person-name end-of-line)))) (def greeting-friend2 (create-greeting-function2 "Hi")) (def greeting-neighbour2 (create-greeting-function2 "Hello")) (greeting-friend2 "Tom") ; "Hi Tom!" (greeting-neighbour2 "Nancy") ; "Hello Nancy!"
It’s clear that if the
calculate-how-to-end-sentence function always returns the same output (it’s pure function), it’s better to execute it outside of the
(fn ...). In my example it would be even faster to
(def end-of-sentence (calculate-how-to-end-sentence)) instead of calculating it inside
Could you please help me understand, when is the actual work (
calculate-how-to-end-sentence calculation) done in case of the second function? I know it is not done when I run
greeting-friend2. Which is good! But is it done when the program starts or when it is compiled?