Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Side effects not realized without deref

From clojure for the brave and true:

(defmacro enqueue
  [q concurrent-promise-name & work]
  (let [concurrent (butlast work)
        serialized (last work)]
    `(let [~concurrent-promise-name (promise)]
       (future (deliver ~concurrent-promise-name (do ~@concurrent)))
       (deref ~q)
       ~serialized
       ~concurrent-promise-name)))
(defmacro wait
  "Sleep `timeout` seconds before evaluating body"
  [timeout & body]
  `(do (Thread/sleep ~timeout) ~@body))
(time @(-> (future (wait 200 (println "'Ello, gov'na!")))
           (enqueue saying (wait 400 "Pip pip!") (println @saying))
           (enqueue saying (wait 100 "Cheerio!") (println @saying))))

If I comment out the (deref ~q) line, then only "Cheerio!" is printed. Why do I need deref here to get other side effects?

like image 875
qed Avatar asked Sep 27 '22 21:09

qed


1 Answers

If you comment out (deref ~q), the code passed with q is never evaluated, so the nested futures don't come into existence.

Macroexpansion:

(macroexpand '(-> (future (wait 200 (println "'Ello, gov'na!")))
                  (enqueue saying (wait 400 "Pip pip!") (println @saying))
                  (enqueue saying (wait 100 "Cheerio!") (println @saying))))
;;-> ....
(clojure.pprint/pp)

(let*
 [saying (clojure.core/promise)]
 (clojure.core/future
   (clojure.core/deliver saying (do (wait 100 "Cheerio!"))))
 ;; no code ended up here...
 (println @saying)
 saying)
like image 118
Leon Grapenthin Avatar answered Oct 01 '22 00:10

Leon Grapenthin