
On 31/08/2015, at 8:27 pm, Alexey Muranov
In my opinion, with such interpretation there can be no documented side effects: if some effect is documented, it is purported (an probably used by someone), so not secondary.
Let's see a piece of actual Java code, not written by me. public class Record { private static final AtomicLongFieldUpdater<Record> VERSION = AtomicLongFieldUpdater.newUpdater(Record.class, "version"); private volatile long version = 0; public long update() { return VERSION.incrementAndGet(this); // THIS LINE IN JAVA } } For comparison, here's basically the same thing in C on OSX: struct Record { volatile int64_t version = 0; }; // Atomic this->version++ int64_t update(struct Record *this) { return OSAtomicIncrement64(&this->version); // THIS LINE IN C } THIS LINE IN C has an effect. It's obvious from the code that the variable `version' may be affected. THIS LINE IN JAVA doesn't as much as mention `version'. Surely there is a qualitative difference here that *matters*? Historic note: Java forbade 'var' or 'reference' parameters in the name of object-oriented purity. i have never been able to figure out what they meant. What they have instead is, and I kid you not, AtomicLongFieldUpdate is an official Java public class, is POINTER ARITHMETIC. (AtomicLongFieldUpdater basically holds a reference to a class and an offset within that class, which gets added to the argument to find the actual variable.) I just learned about AtomicLongFieldUpdater yesterday and still feel sick. Java just moved from "I don't particularly like it but it could be worse" to "heck, I might as well just use C" in my estimation. What I am still having difficulty swallowing is the Java enthusiasts who think this feature is wonderful. But this is a Haskell mailing list, not a Java or C one. For *Haskell*, the type system doesn't encode *all* the effects of an operation (although a functional language type system *could* do so), but it forces you to reveal that an operation has *some* effect other than returning a value and *encourages* you to factor your state space into chunks smaller than the whole world. If you have two state monads and you need to update both, you *know* you have an issue.