Let me add a couple of comments, both from a clojure perspective and from other languages.
First, I have used this pattern in clojure and similar languages. I find it is often useful when I need to deal with multiple functions mutating the same state. In clojure, I used this to make little sloppy UI objects that all reference the same paintable thing, for instance. That ((:reset-state drawable-thingy) 13) was a quick and casual thing. But it encourages you to use one of the functional programming anti-patterns (which is very common in OO languages): A function of no arguments with no return value. If you want your functions to be pure and side-effect free, then you know that a function with no return value does nothing. (Or more concisely, if it does something it does it through a side effect, so it isn't pure and side effect free). And pure and side effect free functions are useful for a variety of reasons. And one of the things clojure has worked hard to do (and one of my favorite features of the language) is to embrace this by having immutable structures everywhere. This then allows the STM implementation and a bunch of good stuff. So I'd say your pattern isn't very idiomatic, or perhaps is only idiomatic if you want to encapsulate mutable state with a set of cooperating functions without declaring a protocol. Instead what you could do, as Logan points out, is separate your state (which is returned by a no-arg constructing function) from your 'modifiers' (which really clone and return a modified version. But there's one problem you run into in the client code you posted. Rather than the full stopwatch version, here's a very similar counter pattern. (defn counter [] {:count 0} ) (defn icount [counter] (update counter :count inc)) (defn dcount [counter] (update counter :count dec)) (def getcount :count) (-> (counter) (icount) (icount) (dcount) (icount) (getcount)) OK so that returns 2 as we would expect. But if you want to use this inside your code, you need to 'stow away' the counters somewhere. Lets say you have something like (* (inc 2) 4) and you want to intersperse those counts. I end up with something that looks like this (let [ct (counter) a 2 ct (icount ct) b (inc a) ct (icount ct) d (* 4 b) ] [ d (getcount ct) ] ) And in your original example, where you are calling start and stop in what is basically procedural code that gets a bit nasty. Where to put that counter is actually a problem which is section 2.3 of a very famous pape <https://cse.sc.edu/~mgv/csce330f16/wadler_monadsForFP_95.pdf>r, and it seems those ideas are kicking around the clojure community too, unsurprisingly. But if you don't want to dive into that, you can still end up making your program easier by keeping your state and count in a map and then having an operator to count the functions. (defn value-counter [ivalue] {:count 0 :value ivalue} ) (defn icount [counter] (update counter :count inc)) (defn dcount [counter] (update counter :count dec)) (def getcount :count) (defn count-ops [c f & arguments ] (let [cn (icount c) nv (apply f (:value cn) arguments) ] (assoc cn :value nv) ) ) (-> (value-counter 2) (count-ops inc) (count-ops * 4) ) Which returns { :count 2 :value 12 } as you'd hope. Hope that helps! On Sunday, December 11, 2016 at 2:41:14 AM UTC-5, Didier wrote: > > 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.