On Dec 31, 2008, at 12:30 AM, Mark Engelberg wrote:

>
> On Tue, Dec 30, 2008 at 8:38 PM, Rich Hickey <richhic...@gmail.com>  
> wrote:
>> There's simply no value for Clojure to add to a simple mutable box.
>> Clojure does provide the tools for low-level mutation - access to
>> Java. You can wrap that in whatever functions/macros you like.
>>
>
> There's no way to use the @ dereferencing syntax for a custom mutable
> box, right?

Not true. Just implement clojure.lang.IRef and deref/@ will work.

> The sample I gave would be considerably harder to read if
> you had to use (box-ref u) instead of @u everywhere.
>
>> OTOH, atom-set just invites the read-modify-write race conditions
>> swap! was meant to avoid.
>
> Yes, but not every write to an atom is going to be a read-modify-write
> kind of change, which is why it feels odd to always be limited to
> swap!.
>

It doesn't matter that it's not a read-modify-write change, it matters  
that you think about other consumers of the atom. swap! makes you do  
that.

> Since my examples emphasized the "simple mutable box" benefits of
> having atom-set, and you didn't find that compelling, let's go back to
> the discussion earlier in this thread about using an atom to maintain
> a counter that increments to generate unique IDs.  You've already
> stated that this is one of the uses that is a good fit for atom.
>
> It would be entirely reasonable to want to, under certain conditions,
> to reset the counter to 0.  When you reset to 0, that's just a
> straight write.  Having to say (swap! counter (constantly 0)) feels
> convoluted, and somewhat obscures the fact that this change is not
> dependent on the previous state of the atom.  Furthermore, by having
> to represent this reset as a swap, the counter reset might not happen
> as quickly as one would like.  If there is a lot of contention and
> other threads are in the process of incrementing the counter, the
> reset might fail to go through for a while, because the value is
> frequently changed by other threads between the unnecessary read and
> the write of 0.  An atom-set would not only reflect the intentions of
> the code better, but would provide better performance for the times
> where a read is irrelevant to the value being written.
>

This is a theoretical argument again, and remains unconvincing. (swap!  
counter (constantly 0)) may feel bad, but it should - you're trashing  
a shared reference with no regard for its contents. And if you have  
code where the counter is so hot a one-time swapping reset is a perf  
issue, you have bigger problems.

One thing is certain, right now code like this is unlikely:

(let [val (inc @a)]
   (swap! a (constantly val)))

Whereas with atom-set in the API, code like this is likely:

(atom-set a (inc @a)) ;broken - race condition

after all, it looks just like its (correct) ref counterpart:

(ref-set r (inc @r))

> Yes, atom-set invites a certain potential for misuse, but atoms
> already require a certain degree of care.
>

This is not the kind of criteria I want to use when designing. With  
that logic Clojure could just be a free-for-all like Java, which also  
requires a 'certain degree of care'.

That said, I think a big part of the problem here lies in the name. If  
it was e.g. reinitialize-atom or reset-atom I might feel differently.

I also think that your use cases for atoms for local mutation are a  
mismatch. atoms are about sharing. You really want something else for  
private/local mutable references, and I have some ideas for that.

Rich


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

Reply via email to