Logan's point about being able to add new functions on a stopwatch is 
valid. That's often the argument to why protocols are better then classic 
OO. Though I still feel like in some scenarios, I think this is a good 
pattern, and can serve us better, the stopwatch being one good example.

Nothing in the pattern necessitate this to be mutable either, though I 
guess this pattern does seem to have some of its advantages from when you 
need mutability for some reason. Then I like how it isolates the mutable 
data behind the functionality.

It feels like a lighter weight version of both OO and protocols/records. 
I'm curious to benchmark it against records, which is what I would have 
used before for something like a stopwatch.

I think this could come in handy when doing libraries with options. My 
current pattern was to have a function create an options, and then the user 
would need to manage the options map, and pass it to all my library 
functions. Or I would use a var instead the library to store the options 
map, and offer it as a binding so users could rebind their own options. The 
problem with the latter is that you can't run the library with two 
different option set at the same time, while the former forces you to have 
to manage an options map and pass it around everywhere. So I feel there's 
something I could do here, with wrapping everything in this pattern, and 
having the options be captured in the closure.

On Friday, 9 December 2016 23:47:34 UTC-8, Didier 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.

Reply via email to