Re: Closure for object pattern? A good idea?

2016-12-17 Thread Rafo Ufoun
Very clear thank you ! 

I can't wait to know these concept as I am discovering clojure with the 
'Functionnal programming for OO programmer' book. Thank you again

Le samedi 17 décembre 2016 18:53:31 UTC-5, James Reeves a écrit :
>
> On 17 December 2016 at 22:13, Rafo Ufoun  > wrote:
>
>> I'm a real newbe to clojure and functionnal programming but reading your 
>> answer raised a question : 
>>
>> Where do you "store" the stopwatch object which you are passing to all 
>> your functions ? 
>>
>> I understand that mutability is not needed to develop the functions you 
>> described but all of them take a stopwatch as as an argument. This 
>> stopwatch must be stored somewhere to call these functions against ?
>>
>
> Sure. At its simplest you could just store the stopwatch as a local 
> binding. For example, lets say we create an input loop:
>
>   (loop [stopwatch zeroed-stopwatch]
> (wait-for-button)
> (if (started? stopwatch)
>   (let [stopped-stopwatch (stop stopwatch)]
> (println (elapsed stopped-stopwatch))
> (recur stopped-stopwatch)
>   (recur (start stopwatch
>
> The state of the stopwatch is stored as a loop variable. If we didn't want 
> an infinite loop, we could use a let form instead to similar effect.
>
> If we have a more traditional GUI, then we have to communicate across 
> threads, and for that we'd use an atom (or possible a ref):
>
>   (let [stopwatch (atom zeroed-stopwatch]
> (on-click button (fn [evt] (swap! stopwatch toggle))
> (on-tick label (fn [evt] (set-text label (elapsed @stopwatch
>
> Does that make things clearer?
>
> - James
>

-- 
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.


Re: Closure for object pattern? A good idea?

2016-12-17 Thread James Reeves
On 17 December 2016 at 22:13, Rafo Ufoun  wrote:

> I'm a real newbe to clojure and functionnal programming but reading your
> answer raised a question :
>
> Where do you "store" the stopwatch object which you are passing to all
> your functions ?
>
> I understand that mutability is not needed to develop the functions you
> described but all of them take a stopwatch as as an argument. This
> stopwatch must be stored somewhere to call these functions against ?
>

Sure. At its simplest you could just store the stopwatch as a local
binding. For example, lets say we create an input loop:

  (loop [stopwatch zeroed-stopwatch]
(wait-for-button)
(if (started? stopwatch)
  (let [stopped-stopwatch (stop stopwatch)]
(println (elapsed stopped-stopwatch))
(recur stopped-stopwatch)
  (recur (start stopwatch

The state of the stopwatch is stored as a loop variable. If we didn't want
an infinite loop, we could use a let form instead to similar effect.

If we have a more traditional GUI, then we have to communicate across
threads, and for that we'd use an atom (or possible a ref):

  (let [stopwatch (atom zeroed-stopwatch]
(on-click button (fn [evt] (swap! stopwatch toggle))
(on-tick label (fn [evt] (set-text label (elapsed @stopwatch

Does that make things clearer?

- James

-- 
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.


Re: Closure for object pattern? A good idea?

2016-12-17 Thread Gregg Reynolds
On Dec 10, 2016 1:47 AM, "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?


have you looked at Protocol?  that's the way I'd do it.

g

-- 
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.


Re: Closure for object pattern? A good idea?

2016-12-17 Thread Rafo Ufoun
I'm a real newbe to clojure and functionnal programming but reading your 
answer raised a question : 

Where do you "store" the stopwatch object which you are passing to all your 
functions ? 

I understand that mutability is not needed to develop the functions you 
described but all of them take a stopwatch as as an argument. This 
stopwatch must be stored somewhere to call these functions against ?

Le samedi 10 décembre 2016 21:51:27 UTC-5, James Reeves a écrit :
>
> 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  
> 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 clo...@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+u...@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+u...@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.


Re: Closure for object pattern? A good idea?

2016-12-11 Thread paul
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 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 

Re: Closure for object pattern? A good idea?

2016-12-10 Thread Didier
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.


Re: Closure for object pattern? A good idea?

2016-12-10 Thread James Reeves
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  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.


Re: Closure for object pattern? A good idea?

2016-12-10 Thread Logan Buckley
I feel like you would be better off separating functions from the data they 
operate on here. In this case, you could represent the state of a stopwatch 
with a map containing the start time and the time elapsed, and have 
functions `stop`, `reset`, `start`, etc that take the stopwatch data 
structure as an argument and compute an answer or return a new stopwatch 
data structure as needed. If you need to share the state of the stopwatch 
you can always put that map in an atom when you need to.

This has the additional benefit that you can implement new functions on the 
stopwatch without changing the implementation stopwatch data structure 
itself, while in the case of the closure you need to change the 
implementation of `new-stopwatch` if you want to be able to do anything 
else with the stopwatch data - sort of the same rationale for 
clojure.core's extensive use of functions that operate on seqs instead of 
many specialized data structures.

You don't gain much by storing the state in a closure unless you need to 
guarantee that the user of your code can't access it, which with immutable 
data structures isn't often necessary.

-Logan


On Saturday, December 10, 2016 at 2:47:34 AM UTC-5, 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.


Closure for object pattern? A good idea?

2016-12-09 Thread Didier
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.