Yes, upon second thought I saw exactly what you mean. I think you make an important point: when talking about the STM we need to look at the wider picture. Where a mutable-by-default language needs the STM, Clojure gets by with just atoms because a single swap! call can do any number of mutations at once. We naturally tend to design things so that everything related fits into a single structure and the result simply doesn't need the STM. Therefore the threshold of complexity beyond which you need an STM solution in Clojure is quite a bit higher than usual.
An important angle to my experience with Clojure that I now see must be added is that I never got frustrated with Clojure's STM because it failed to deliver: I just found that my solutions worked perfectly well without it. On Tuesday, December 11, 2012 10:53:08 PM UTC+1, stuart....@gmail.com wrote: > > Is it possible to write a reducing function that mutates a list in > Clojure? Sure. But I think it is absurdly unlikely that it would happen by > accident. My 1% chance wasn't hedging against that case -- I was hedging > against a bug in reduce itself. > > I don't really see even a 1% likelihood of either of those, but I played > D&D as a kid and learned that even the most unlikely things happen one time > in twenty. :-) > > Stu > > > On Tue, Dec 11, 2012 at 3:30 PM, Marko Topolnik > <marko.t...@gmail.com<javascript:> > > wrote: > >> Just curious, how did you immediately eliminate the possibility that the >> reducing function was mutating the list that is being reduced? No >> concurrency involved. In regular Java the 95% leading cause of CME is >> precisely that. >> >> Anyway, this applies to immutable structures per se, whether combined >> with atoms, refs, or none. But a full wartime story must also cover how the >> solution avoids the pitfalls of retryable transactions. This is the real >> sore point in my experience, and the one which makes STM an all-or-nothing >> enterprise. >> >> >> On Tuesday, December 11, 2012 8:53:40 PM UTC+1, stuart....@gmail.comwrote: >>> >>> Hi Paul, >>> >>> Here is a real-world, production software example of the advantage of >>> values+refs over mutable objects and locks. A Datomic user reported the >>> following stack trace as a potential bug: >>> >>> 12:45:43.480 [qtp517338136-84] WARN c.v.a.s.p.e.UnknownExceptionH**andler >>> - UnknownExceptionHandler: null >>> java.util.ConcurrentModificati**onException: null >>> at >>> java.util.ArrayList$Itr.checkF**orComodification(ArrayList.**java:819) >>> ~[na:1.7.0_07] >>> at java.util.ArrayList$Itr.next(A**rrayList.java:791) >>> ~[na:1.7.0_07] >>> at clojure.core.protocols$fn_**_5871.invoke(protocols.clj:76) >>> ~[clojure-1.4.0.jar:na] >>> at >>> clojure.core.protocols$fn_**_5828$G__5823__5841.invoke(pro**tocols.clj:13) >>> ~[clojure-1.4.0.jar:na] >>> at clojure.core$reduce.invoke(cor**e.clj:6030) >>> ~[clojure-1.4.0.jar:na] >>> >>> I immediately had 99% confidence that the bug was in user code, and even >>> a pretty good idea what went wrong. A call to "reduce" is a functional >>> transformation, and it expects to be passed values. The exception clearly >>> indicates a violation of that contract, and is caused by cross-thread >>> aliasing and mutation in the calling code. >>> >>> Regards, >>> Stu >>> >> > -- 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