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