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 [email protected]
Note that posts from new members are moderated - please be patient with your
first post.
To unsubscribe from this group, send email to
[email protected]
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 [email protected].
For more options, visit https://groups.google.com/d/optout.