Skip to content

Instantly share code, notes, and snippets.

@pervognsen
Created April 4, 2010 15:13
Show Gist options
  • Save pervognsen/355456 to your computer and use it in GitHub Desktop.
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)
@kotarak
Copy link

kotarak commented Apr 4, 2010

Passing a thunk into delay is doing things twice. You can write the lazy-ref macro as

(defmacro lazy-ref
  [form]
  `(lazy-ref* (delay ~form)))

and pass the delay directly.

Also passing the value of the Ref in lazy-alter as the last argument is inconsistent with the non-lazy alter.

(defn lazy-alter
  [r f & args]
  (alter (:ref r) #(delay (apply f @% args))))

@pervognsen
Copy link
Author

Thanks, Meikel. Clojure's preferred currying order always surprises me.

@kotarak
Copy link

kotarak commented Apr 5, 2010

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.

@pervognsen
Copy link
Author

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.

@kotarak
Copy link

kotarak commented Apr 5, 2010

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.

@pervognsen
Copy link
Author

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment