-
-
Save pervognsen/355456 to your computer and use it in GitHub Desktop.
(deftype LazyRef [ref] | |
clojure.lang.IDeref (deref [] (force @ref))) | |
(defn lazy-ref* [thunk] | |
(LazyRef (ref (delay (thunk))))) | |
(defmacro lazy-ref [form] | |
`(lazy-ref* (fn [] ~form))) | |
(defn lazy-alter [r f & args] | |
(alter (:ref r) (fn [x] (delay (apply f (concat args [(force x)])))))) | |
;; Example | |
(def r1 (lazy-ref (do (println "r1 forced") 42))) | |
(println @r1) | |
(println @r1) | |
(def r2 (lazy-ref (do (println "r2 forced") 42))) | |
(dosync (lazy-alter r2 (fn [x y] (println "r2 alter forced") (+ x y)) 8)) | |
(println "after lazy-alter") | |
(println @r2) | |
(println @r2) |
Thanks, Meikel. Clojure's preferred currying order always surprises me.
There might be arguments for any order. For clojure there is at least some rationale by Rich.
Sidenote on a pet peeve of mine (bashing unconditional point-free style): Looking at constructs like (apply f (concat args [x]))
casts some doubt on the superiority and elegance of point-free style.
I don't think anyone programs in an unconditional point-free style, so you are bashing a strawman. As with everything in programming, the value of something like point-free style should be judged on a case by case basis. There wasn't any point-free code in what I posted.
There are some community members advocating point-free style quite heavily. Hard at the limit to point-lessness, IMHO.
Anyway, I was not refering to your code. In fact I like your code. You did something similar to Refs I did to Maps with my lazymap library.
I've programmed a lot in Haskell and point-free style is often the right answer there. Clojure makes different semantic and syntactic trade-offs, so I find that it's less frequently the right answer. In any case, I consider use of expression threading macros like -> and ->> to be "morally" the same as point-free style.
Passing a thunk into delay is doing things twice. You can write the
lazy-ref
macro asand pass the delay directly.
Also passing the value of the Ref in
lazy-alter
as the last argument is inconsistent with the non-lazyalter
.