You don't need mutability to represent a stopwatch. (defn start [stopwatch] (assoc stopwatch ::start-time (System/currentTimeMillis)))
(defn elapsed-since-started [stopwatch] (- (System/currentTimeMillis) (::start-time stopwatch))) (defn stop [stopwatch] (-> stopwatch (dissoc ::start-time) (update ::elapsed (fnil + 0) (elapsed-since-started stopwatch)))) (defn elapsed [stopwatch] (::elapsed (stop stopwatch) 0) (defn reset [stopwatch] (dissoc stopwatch ::start-time ::elapsed)) Mutability is typically only necessary for two reasons: 1. Communication across threads 2. Performance - James On 10 December 2016 at 07:47, Didier <didi...@gmail.com> wrote: > I'm wondering what everyone thinks of using closures to mimic a simplistic > object system in Clojure? I'm not sure what to think of it yet, but the > idea is that you wrap object fields inside a closed function, and it > returns a map of methods that operates over those fields. > > Here's an example of using this pattern to implement a StopWatch: > > (import [java.lang System]) > (defn new-stopwatch [] > (let [start-time (atom nil) > elapsed (atom 0)] > {:start (fn [] > (when (nil? @start-time) > (reset! start-time (System/currentTimeMillis)))) > :stop (fn [] > (when-not (nil? @start-time) > (reset! elapsed > (+ @elapsed > (- (System/currentTimeMillis) @start-time))) > (reset! start-time nil)) > @elapsed) > :reset (fn [] > (reset! start-time nil) > (reset! elapsed 0) > @elapsed) > :elapsed (fn [] > (if-not (nil? @start-time) > (- (System/currentTimeMillis) @start-time) > @elapsed))})) > > (let [sw1 (new-stopwatch) > sw2 (new-stopwatch)] > ((:start sw1)) > ((:start sw2)) > (Thread/sleep 100) > ((:reset sw1)) > ((:start sw1)) > (println (str "Elapsed for SW1: " ((:elapsed sw1)))) > (println (str "Elapsed for SW2: " ((:elapsed sw2)))) > (Thread/sleep 100) > (println (str "SW1: " ((:stop sw1)))) > (println (str "SW2: " ((:stop sw2))))) > > I find for certain things, like a stopwatch, this pattern is actually > pretty nice. I can't think of any alternative way to do this in Clojure > that I'd like better actually. > > What are your thoughts? > > -- > You received this message because you are subscribed to the Google > Groups "Clojure" group. > To post to this group, send email to clojure@googlegroups.com > Note that posts from new members are moderated - please be patient with > your first post. > To unsubscribe from this group, send email to > clojure+unsubscr...@googlegroups.com > For more options, visit this group at > http://groups.google.com/group/clojure?hl=en > --- > You received this message because you are subscribed to the Google Groups > "Clojure" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to clojure+unsubscr...@googlegroups.com. > For more options, visit https://groups.google.com/d/optout. > -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.