Re: Immutable or Effectively Immutable?
It will also see versions of any object or array referenced by those final fields that are **at least as up-to-date as the final fields** are. To me this means that the value of the final field will be correctly published **as of the time it was assigned**. So in your example, there are two problems, I think: * The modification that is done at the second line of the constructor of Foo is **not**, in my understanding, safely published, since it is more recent than the final field's assignment (reversing the two lines *would*, in my understanding, safely publish the array, though it would still not guarantee an ordering between the fill(1) and fill(2) operations in this case); * The value of the bytes array, when the second thread gets hold of it, is not specified: the bytes variable itself is volatile, but not its content, so the assignment to bytes must have occurred, but not the filling with ones. So, since the previous value of (the contents of) bytes is not specified, and the next value of bytes is not safely published, in my view, for this code, all bets are off as to the value seen by the first thread on the match line. No combination of ones and twos would surprise me (and I'm not even so sure about zeroes). On 9 May 2014 17:41, Mike Fikes mikefi...@me.com wrote: Thanks Alexandru! That was insightful. :) Even the JLS's (non-normative?) text is confusing IMHO. Section 17.5 ends with this paragraph: The usage model for final fields is a simple one. Set the final fields for an object in that object's constructor. Do not write a reference to the object being constructed in a place where another thread can see it before the object's constructor is finished. If this is followed, then when the object is seen by another thread, that thread will always see the correctly constructed version of that object's final fields. It will also see versions of any object or array referenced by those final fields that are at least as up-to-date as the final fields are. If you read that paragraph, it would lead you to believe the bit in bold would be applicable to the program below. It seems that the key is, as you pointed out, simply extending the concept of this escaping to cover mutable references stored during construction. import java.util.Arrays; public class Main { static class Foo { final byte[] bytes; Foo(byte[] bytes) { this.bytes = bytes; Arrays.fill(this.bytes, (byte) 2); } } static volatile byte[] bytes; static volatile Foo foo; public static void main(String[] args) { new Thread(new Runnable() { public void run() { // Create an array filled with 1s and spin for other thread bytes = new byte[1024*1024]; Arrays.fill(bytes, (byte) 1); while (foo == null) {} // Check to see if we get the array contents set by other thread byte[] expected = new byte[1024*1024]; Arrays.fill(expected, (byte) 2); boolean match = Arrays.equals(expected, foo.bytes); System.out.println(match); // Will print false at times } }).start(); new Thread(new Runnable() { public void run() { // Spin for first thread while (bytes == null) {} // Create an immutable object using bytes, while mutating bytes prior to construction completion and publication foo = new Foo(bytes); } }).start(); } } On Thursday, May 8, 2014 4:43:10 PM UTC-4, Alexandru Nedelcu wrote: On Wed, May 7, 2014 at 6:31 AM, Alex Miller al...@puredanger.com wrote: It does matter with regard to visibility across threads - your example does not use a synchronization mechanism and there is no guarantee that other threads will ever see those changes (so don't ever ever do that :). But if you stick to the normal Clojure apis, all is good. I'd highly recommend reading JCIP to dive into the details. Final field freeze is particularly weird and it baked my noodle when I first encountered it - here's a blog I wrote about it approx 697 years ago in internet time (and Brian Goetz backs me up in the comments :) http://tech.puredanger.com/2008/11/26/jmm-and-final-field-freeze/ I believe that while JCIP is useful, it is also confusing, because it is trying to explain Java’s memory model in layman’s terms. I recently experienced “enlightenment”, by making an effort to understand how things work at a lower level. Happens-before relationships / ordering guarantees are given by the compiler, in combination with the CPU, with the rules being implied by usage of memory fences (barriers). Without ordering guarantees, several things can happen - the compiler could optimize the code by reordering or eliminating instructions, the CPU might optimize the code
Re: Immutable or Effectively Immutable?
;; I think this shed should be painted red (def immutable-string foo) (def ^java.lang.reflect.Field value-field (doto (.getDeclaredField String value) (.setAccessible true))) (aset (.get value-field immutable-string) 1 \i) (aset (.get value-field immutable-string) 2 \e) (println immutable-string) On Wed, May 7, 2014 at 11:15 AM, Mike Fikes mikefi...@me.com wrote: I would offer that the key distinction is whether final is used: This prescribes what you must do when using the object. Take Date for example. You can't just pass one directly from one thread to another. The receiving thread could read a date associated with System.currentTimeMillis() of 0. But, String, since it uses final on its char[], fundamentally changes this. (If the final keyword were not present in String, even though you have no way to change its char[], it would be broken with respect to threading semantics.) On Wednesday, May 7, 2014 10:35:04 AM UTC-4, Andy Fingerhut wrote: Sorry if I'm beating a dead horse here. I agree that my example is not using published Clojure APIs, and I never do that kind of thing in a Clojure program, except as an example that PersistentVector's are mutable if you use Java APIs instead of restricting yourself to Clojure APIs. You don't even need to use reflection in Java or know about JVM security policies to mutate them (I am not suggesting that Clojure should be changed in any way here). I've actually got a copy of Java: Concurrency in Practice, and looked up (some of) what they say about immutability. Here is one definition they give of immutability, with some preceding text. I have added emphasis to one phrase: Neither the Java Language Specification nor the Java Memory Model formally defines immutability, but __immutability is *not* equivalent to simply declaring all fields of an object 'final'__. An object whose fields are all final may still be mutable, since final fields can hold references to mutable objects. An object is *immutable* if: + Its state cannot be modified after construction; + All its fields are 'final'; and + It is *properly constructed* (the 'this' reference does not escape during construction). I have no argument with PersistentVector satisfying the 2nd and 3rd bullet points above, but (1) seems not to hold. According to JCIP's definition of effectively immutable (Objects that are not technically immutable, but whose state will not be modified after publication), PersistentVector appears to me to be effectively immutable, but not truly immutable. Andy On Tue, May 6, 2014 at 8:31 PM, Alex Miller al...@puredanger.com wrote: Hey Andy, It does matter with regard to visibility across threads - your example does not use a synchronization mechanism and there is no guarantee that other threads will ever see those changes (so don't ever ever do that :). But if you stick to the normal Clojure apis, all is good. I'd highly recommend reading JCIP to dive into the details. Final field freeze is particularly weird and it baked my noodle when I first encountered it - here's a blog I wrote about it approx 697 years ago in internet time (and Brian Goetz backs me up in the comments :) http://tech.puredanger.com/2008/11/26/jmm-and-final-field-freeze/ Alex On Tuesday, May 6, 2014 7:35:43 PM UTC-5, Andy Fingerhut wrote: Alex, I may be unfamiliar with the definitions of truly immutable and effectively immutable being used here, but if I can mutate the contents of a Java Object array that is a final field after an object is constructed, does it really matter that much if it is final? It is trivially easy to mutate using Java access. Here is the example that I mentioned earlier in this thread, copied here for convenience: user= (def v [1 2 3]) #'user/v user= (class v) clojure.lang.PersistentVector user= v [1 2 3] user= (aset (.tail v) 1 -2) -2 user= v [1 -2 3] Andy On Tue, May 6, 2014 at 4:49 PM, Alex Miller al...@puredanger.comwrote: The Clojure persistent data structures are truly immutable - all fields are final and referred objects are not mutated after construction so that freeze occurs. One obvious exception are the transient variants ( http://clojure.org/transients). You can look at the code in https://github.com/clojure/clojure/tree/master/src/jvm/clojure/lang - any of the Persistent*.java. On Tuesday, May 6, 2014 4:11:49 PM UTC-5, Mike Fikes wrote: Are the persistent immutable data structures in Clojure truly immutable (using final fields, relying on constructor freezing), or are they mean to be merely effectively immutable (as defined in JICP)? -- 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
Re: Immutable or Effectively Immutable?
In the sample code I pasted, there is nothing to prevent the fill(1) and fill(2) from running concurrently, and essentially write into the same array concurrently. My intent was that the fill(1) be complete before the second thread proceeds. A simple change to have the 1st thread instead fill a temporary byte[] followed by assigning the temporary reference to the static volatile byte[] causes the program to no longer print “false”. This behavior, while it doesn't prove anything, is consistent with the JLS paragraph I quoted. But, it doesn't disprove Alexandru's claim either... -- 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: Immutable or Effectively Immutable?
Alexandru Nedelcu a...@bionicspirit.com writes: On Wed, May 7, 2014 at 5:57 PM, Phillip Lord phillip.l...@newcastle.ac.ukwrote: In general, though, if I write some code like (if (instance? Cons x) (pass-to-another-thread-without-synchronisation x)) I cannot guarantee the result of this because although I know that the head of x is fixed, I cannot guarantee that for the tail. If I know how x is constructed, of course, then I can make this guarantee. On the other hand, that's not the concern of the piece of code you outlined. Because if x wasn't constructed properly and the latest data in it is not visible, there's absolutely nothing you can do about it ;-) Visibility is (or should be) the concern of the producer, not of the consumer. Perhaps I didn't word this well. The problem is with my code is that I only know about the implementation of the head of x. When I talk about construction, I mean, if I know what else is in x. Not clear, sorry! You get the a related problem in Java. List l = Collections.unmodifiedableList(l); Is l now unmodifiable? Well maybe, depending on what happened to it before. What happened to it before is not relevant, because again, there's nothing you can do about it at this point and actually from this consumer's perspective before doesn't exist ... there's only now with the only question being if there are or there will be pending changes that may or may not be published in the future (where future is kind of thread-local). Again, not great wording. l is unmodifiable if it's not be let out anywhere. That's the problem. The reason it's related to the issue in Clojure is that, List is an interface, while Cons is build in terms of an interface. You cannot define immutability (or unmodifiability) in terms of an abstract interface. Java String are immutable. Concrete and final implementation. Concurrency is hard, but it's greatly simplified if you keep the concerns for atomicity and visibility on the producer's side. Not going to disagree with this. I just answered the original question is all:-) Phil -- 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: Immutable or Effectively Immutable?
Thanks Alexandru! That was insightful. :) Even the JLS's (non-normative?) text is confusing IMHO. Section 17.5 ends with this paragraph: The usage model for final fields is a simple one. Set the final fields for an object in that object's constructor. Do not write a reference to the object being constructed in a place where another thread can see it before the object's constructor is finished. If this is followed, then when the object is seen by another thread, that thread will always see the correctly constructed version of that object's final fields. *It will also see versions of any object or array referenced by those final fields that are at least as up-to-date as the final fields are.* If you read that paragraph, it would lead you to believe the bit in bold would be applicable to the program below. It seems that the key is, as you pointed out, simply extending the concept of this escaping to cover mutable references stored during construction. import java.util.Arrays; public class Main { static class Foo { final byte[] bytes; Foo(byte[] bytes) { this.bytes = bytes; Arrays.fill(this.bytes, (byte) 2); } } static volatile byte[] bytes; static volatile Foo foo; public static void main(String[] args) { new Thread(new Runnable() { public void run() { // Create an array filled with 1s and spin for other thread bytes = new byte[1024*1024]; Arrays.fill(bytes, (byte) 1); while (foo == null) {} // Check to see if we get the array contents set by other thread byte[] expected = new byte[1024*1024]; Arrays.fill(expected, (byte) 2); boolean match = Arrays.equals(expected, foo.bytes); System.out.println(match); // Will print false at times } }).start(); new Thread(new Runnable() { public void run() { // Spin for first thread while (bytes == null) {} // Create an immutable object using bytes, while mutating bytes prior to construction completion and publication foo = new Foo(bytes); } }).start(); } } On Thursday, May 8, 2014 4:43:10 PM UTC-4, Alexandru Nedelcu wrote: On Wed, May 7, 2014 at 6:31 AM, Alex Miller al...@puredanger.comjavascript: wrote: It does matter with regard to visibility across threads - your example does not use a synchronization mechanism and there is no guarantee that other threads will ever see those changes (so don't ever ever do that :). But if you stick to the normal Clojure apis, all is good. I'd highly recommend reading JCIP to dive into the details. Final field freeze is particularly weird and it baked my noodle when I first encountered it - here's a blog I wrote about it approx 697 years ago in internet time (and Brian Goetz backs me up in the comments :) http://tech.puredanger.com/2008/11/26/jmm-and-final-field-freeze/ I believe that while JCIP is useful, it is also confusing, because it is trying to explain Java’s memory model in layman’s terms. I recently experienced “enlightenment”, by making an effort to understand how things work at a lower level. Happens-before relationships / ordering guarantees are given by the compiler, in combination with the CPU, with the rules being implied by usage of memory fences (barriers). Without ordering guarantees, several things can happen - the compiler could optimize the code by reordering or eliminating instructions, the CPU might optimize the code by reordering or eliminating instructions and - what bits beginners the most - today’s multi-core CPUs are tricky, as each CPU has a store buffer that’s local to each core (i.e. other cores cannot see it) and published values only become visible to other cores when the store buffer gets flushed to the L1 cache. And you have no guarantee that this flush will *ever* happen, or even after it happens, you have no guarantee that other processors that already have a cached value will make an effort to read the more up-to-date value … unless ordering semantics are enforced. And actually thinking in terms of flushes to memory is dangerous, as nothing you do guarantees a flush - everything being relative, specified in terms of happens-before relationships, implied by memory barriers. And memory barriers are tricky beasts, as they come in multiple shapes and sizes. The JSR 133 Cookbookhttp://gee.cs.oswego.edu/dl/jmm/cookbook.htmlis a useful document for shedding some light on how they work. In particular, for final fields, you get a guarantee for a *StoreStore*memory barrier, like so: x.finalField = v; *StoreStore*; sharedRef = x; This guarantee basically says that the finalFields’ value will always be stored before the write sharedRef
Re: Immutable or Effectively Immutable?
On Wed, May 7, 2014 at 6:31 AM, Alex Miller a...@puredanger.com wrote: It does matter with regard to visibility across threads - your example does not use a synchronization mechanism and there is no guarantee that other threads will ever see those changes (so don't ever ever do that :). But if you stick to the normal Clojure apis, all is good. I'd highly recommend reading JCIP to dive into the details. Final field freeze is particularly weird and it baked my noodle when I first encountered it - here's a blog I wrote about it approx 697 years ago in internet time (and Brian Goetz backs me up in the comments :) http://tech.puredanger.com/2008/11/26/jmm-and-final-field-freeze/ I believe that while JCIP is useful, it is also confusing, because it is trying to explain Java’s memory model in layman’s terms. I recently experienced “enlightenment”, by making an effort to understand how things work at a lower level. Happens-before relationships / ordering guarantees are given by the compiler, in combination with the CPU, with the rules being implied by usage of memory fences (barriers). Without ordering guarantees, several things can happen - the compiler could optimize the code by reordering or eliminating instructions, the CPU might optimize the code by reordering or eliminating instructions and - what bits beginners the most - today’s multi-core CPUs are tricky, as each CPU has a store buffer that’s local to each core (i.e. other cores cannot see it) and published values only become visible to other cores when the store buffer gets flushed to the L1 cache. And you have no guarantee that this flush will *ever* happen, or even after it happens, you have no guarantee that other processors that already have a cached value will make an effort to read the more up-to-date value … unless ordering semantics are enforced. And actually thinking in terms of flushes to memory is dangerous, as nothing you do guarantees a flush - everything being relative, specified in terms of happens-before relationships, implied by memory barriers. And memory barriers are tricky beasts, as they come in multiple shapes and sizes. The JSR 133 Cookbook http://gee.cs.oswego.edu/dl/jmm/cookbook.htmlis a useful document for shedding some light on how they work. In particular, for final fields, you get a guarantee for a *StoreStore* memory barrier, like so: x.finalField = v; *StoreStore*; sharedRef = x; This guarantee basically says that the finalFields’ value will always be stored before the write sharedRef = x happens. Or in other words, once the constructor of x is finished and the value stored inside a sharedRef, the finals are already fully initialized. And this extends to whatever writes that happened in the object stored in that final field too. This assumes that this didn’t escape during construction - in which case the above guarantee becomes meaningless for threads that already saw object x. As an aside, a StoreStore fence on X86 is a no-op, as stores on X86 are ordered, but for other processors this is not true and the compiler can and does reorder instructions by itself. Also consider doing something like: final int[] field = new int[] {1,2,3,4} Even though that array is not immutable, the array and the values in it will be visible once the final field itself becomes visible, again because of the store ordering guarantee. But this doesn’t hold if that array reference has been seen before, so this doesn’t work as people might think: final int[] field; public Constructor(int[] arr) { field = arr } My initial impression was that a final field store behaves like a volatile write. That’s not true. A volatile write is *preceded* by a StoreStore, while a final write is succeeded by one. Also, a volatile write followed by a volatile read guarantees a Store/Load memory barrier between the two actions for ordering previous stores with subsequent loads - this is the rule that says that once a volatile is stored, then subsequent reads are ordered after that store (so the volatile read is basically monitor enter and the volatile write is basically monitor exit … the similarity with acquiring locks is not accidental at all) and so threads don’t get stale data. Finals don’t get the same treatment, even though there are similarities between the two … this is also why it is important for this to not escape during construction or for why the array reference received from the outside in the above won’t necessarily be up-to-date when the final will be observed by other threads - again, ordering guarantees are relative. In other words, for finals to work properly, this mustn’t escape during construction and care must be taken when storing references to mutable things received from the outside. -- Alexandru Nedelcu www.bionicspirit.com PGP Public Key: https://bionicspirit.com/key.aexpk -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to
Re: Immutable or Effectively Immutable?
On Wed, May 7, 2014 at 5:57 PM, Phillip Lord phillip.l...@newcastle.ac.ukwrote: In general, though, if I write some code like (if (instance? Cons x) (pass-to-another-thread-without-synchronisation x)) I cannot guarantee the result of this because although I know that the head of x is fixed, I cannot guarantee that for the tail. If I know how x is constructed, of course, then I can make this guarantee. On the other hand, that's not the concern of the piece of code you outlined. Because if x wasn't constructed properly and the latest data in it is not visible, there's absolutely nothing you can do about it ;-) Visibility is (or should be) the concern of the producer, not of the consumer. You get the a related problem in Java. List l = Collections.unmodifiedableList(l); Is l now unmodifiable? Well maybe, depending on what happened to it before. What happened to it before is not relevant, because again, there's nothing you can do about it at this point and actually from this consumer's perspective before doesn't exist ... there's only now with the only question being if there are or there will be pending changes that may or may not be published in the future (where future is kind of thread-local). Concurrency is hard, but it's greatly simplified if you keep the concerns for atomicity and visibility on the producer's side. And if some third-party module or function or class or whatever doesn't respect this rule by delegating such concerns to the consumer, then simply scrap it from the code-base if it's such a big deal - Date is mutable and that's a problem? Use Joda, etc... Java libraries also document when something is thread-safe and if that's left unspecified, it means that it isn't. That's how people working with C++ also keep their sanity in regards to memory management - i.e. when a producer passes along a pointer or reference of something to a consumer, the sanest thing to do is to consider deallocation or other life cycle issues as the responsibility of the producer, unless it's very explicit in the exposed API that the consumer should handle it. -- Alexandru Nedelcu www.bionicspirit.com PGP Public Key: https://bionicspirit.com/key.aexpk -- 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: Immutable or Effectively Immutable?
Since the data structures and interfaces, they are effectively immutable. Consider this: final public class Cons extends ASeq implements Serializable { private final Object _first; private final ISeq _more; public Cons(Object first, ISeq _more){ this._first = first; this._more = _more; } } Although Cons uses final fields and constructor fields, _more is an ISeq; given that this could be mutable, so could cons. Phil Mike Fikes mikefi...@me.com writes: Are the persistent immutable data structures in Clojure truly immutable (using final fields, relying on constructor freezing), or are they mean to be merely effectively immutable (as defined in JICP)? -- Phillip Lord, Phone: +44 (0) 191 222 7827 Lecturer in Bioinformatics, Email: phillip.l...@newcastle.ac.uk School of Computing Science, http://homepages.cs.ncl.ac.uk/phillip.lord Room 914 Claremont Tower, skype: russet_apples Newcastle University, twitter: phillord NE1 7RU -- 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: Immutable or Effectively Immutable?
Mike, I believe I understand the definition of truly immutable you are using here, and what it means in the JVM as far as synchronization of object values across threads. What seems a bit odd is to use the phrase truly immutable to describe something that is clearly mutable, or at least it is by the definition of mutable: can be modified after construction, which PersistentVector and others can be. Thanks, Andy On Tue, May 6, 2014 at 6:20 PM, Mike Fikes mikefi...@me.com wrote: Hi Andy, Marking Java fields as final has semantics with respect to threading, defined in the JLS in section 17.5 ( http://docs.oracle.com/javase/specs/jls/se5.0/html/memory.html#17.5) If you do this, then it makes it possible to freely pass a truly immutable object instance to another thread and be guaranteed that that other thread will see the value initialized for that field in the constructor. If you don't do this, then the object can still be effectively immutable, which essentially means that you can pass the object to another thread, so long as you do it in a safe manner (using a volatile, or some synchronization mechanism). JCIP helps clarify all of this unfortunately complex topic. The important thing (and key to Closure), is that, if you are implementing the class that you want to be immutable, then if you can mark everything as final, then you truly achieve the benefits immutability give you with concurrency (in short, you need no synchronization whatsoever). If you fail to do this, then you have effective immutability, which is good, but complex and comes with caveats on how you can safely pass objects between threads. JCIP is a great book. But, the approach taken by Clojure makes a lot of the complicated concerns covered by the book largely ignorable, IMHO. On Tuesday, May 6, 2014 8:35:43 PM UTC-4, Andy Fingerhut wrote: Alex, I may be unfamiliar with the definitions of truly immutable and effectively immutable being used here, but if I can mutate the contents of a Java Object array that is a final field after an object is constructed, does it really matter that much if it is final? It is trivially easy to mutate using Java access. Here is the example that I mentioned earlier in this thread, copied here for convenience: user= (def v [1 2 3]) #'user/v user= (class v) clojure.lang.PersistentVector user= v [1 2 3] user= (aset (.tail v) 1 -2) -2 user= v [1 -2 3] Andy On Tue, May 6, 2014 at 4:49 PM, Alex Miller al...@puredanger.com wrote: The Clojure persistent data structures are truly immutable - all fields are final and referred objects are not mutated after construction so that freeze occurs. One obvious exception are the transient variants ( http://clojure.org/transients). You can look at the code in https://github.com/clojure/clojure/tree/master/src/jvm/clojure/lang - any of the Persistent*.java. On Tuesday, May 6, 2014 4:11:49 PM UTC-5, Mike Fikes wrote: Are the persistent immutable data structures in Clojure truly immutable (using final fields, relying on constructor freezing), or are they mean to be merely effectively immutable (as defined in JICP)? -- 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. -- 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
Re: Immutable or Effectively Immutable?
Sorry if I'm beating a dead horse here. I agree that my example is not using published Clojure APIs, and I never do that kind of thing in a Clojure program, except as an example that PersistentVector's are mutable if you use Java APIs instead of restricting yourself to Clojure APIs. You don't even need to use reflection in Java or know about JVM security policies to mutate them (I am not suggesting that Clojure should be changed in any way here). I've actually got a copy of Java: Concurrency in Practice, and looked up (some of) what they say about immutability. Here is one definition they give of immutability, with some preceding text. I have added emphasis to one phrase: Neither the Java Language Specification nor the Java Memory Model formally defines immutability, but __immutability is *not* equivalent to simply declaring all fields of an object 'final'__. An object whose fields are all final may still be mutable, since final fields can hold references to mutable objects. An object is *immutable* if: + Its state cannot be modified after construction; + All its fields are 'final'; and + It is *properly constructed* (the 'this' reference does not escape during construction). I have no argument with PersistentVector satisfying the 2nd and 3rd bullet points above, but (1) seems not to hold. According to JCIP's definition of effectively immutable (Objects that are not technically immutable, but whose state will not be modified after publication), PersistentVector appears to me to be effectively immutable, but not truly immutable. Andy On Tue, May 6, 2014 at 8:31 PM, Alex Miller a...@puredanger.com wrote: Hey Andy, It does matter with regard to visibility across threads - your example does not use a synchronization mechanism and there is no guarantee that other threads will ever see those changes (so don't ever ever do that :). But if you stick to the normal Clojure apis, all is good. I'd highly recommend reading JCIP to dive into the details. Final field freeze is particularly weird and it baked my noodle when I first encountered it - here's a blog I wrote about it approx 697 years ago in internet time (and Brian Goetz backs me up in the comments :) http://tech.puredanger.com/2008/11/26/jmm-and-final-field-freeze/ Alex On Tuesday, May 6, 2014 7:35:43 PM UTC-5, Andy Fingerhut wrote: Alex, I may be unfamiliar with the definitions of truly immutable and effectively immutable being used here, but if I can mutate the contents of a Java Object array that is a final field after an object is constructed, does it really matter that much if it is final? It is trivially easy to mutate using Java access. Here is the example that I mentioned earlier in this thread, copied here for convenience: user= (def v [1 2 3]) #'user/v user= (class v) clojure.lang.PersistentVector user= v [1 2 3] user= (aset (.tail v) 1 -2) -2 user= v [1 -2 3] Andy On Tue, May 6, 2014 at 4:49 PM, Alex Miller al...@puredanger.com wrote: The Clojure persistent data structures are truly immutable - all fields are final and referred objects are not mutated after construction so that freeze occurs. One obvious exception are the transient variants ( http://clojure.org/transients). You can look at the code in https://github.com/clojure/clojure/tree/master/src/jvm/clojure/lang - any of the Persistent*.java. On Tuesday, May 6, 2014 4:11:49 PM UTC-5, Mike Fikes wrote: Are the persistent immutable data structures in Clojure truly immutable (using final fields, relying on constructor freezing), or are they mean to be merely effectively immutable (as defined in JICP)? -- 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
Re: Immutable or Effectively Immutable?
Phil, that's an interesting point. Consider (def x (cons (new java.util.Date) ())) The object identified by x is *mutable*, but if the contained Date will not be modified by the program, then the resulting object can be treated as *effectively immutable, *as you pointed out. But, it would seem that you could pass x to another thread without synchronization, and then safely read the contained Date instance by that thread, because it has been safely published by virtue of having been conveyed by a final field of the Cons instance. Of course, you would run into trouble if you took that Date instance and passed it directly to another thread without synchronization. In other words, you could step outside of the limited profile of the Java memory model that JCIP prescribes treating x as something (useful) between *effectively immutable *and *immutable, *with the end result being that you can treat x as being *immutable.* On Wednesday, May 7, 2014 7:13:31 AM UTC-4, Phillip Lord wrote: Since the data structures and interfaces, they are effectively immutable. Consider this: final public class Cons extends ASeq implements Serializable { private final Object _first; private final ISeq _more; public Cons(Object first, ISeq _more){ this._first = first; this._more = _more; } } Although Cons uses final fields and constructor fields, _more is an ISeq; given that this could be mutable, so could cons. Phil Mike Fikes mike...@me.com javascript: writes: Are the persistent immutable data structures in Clojure truly immutable (using final fields, relying on constructor freezing), or are they mean to be merely effectively immutable (as defined in JICP)? -- Phillip Lord, Phone: +44 (0) 191 222 7827 Lecturer in Bioinformatics, Email: philli...@newcastle.ac.ukjavascript: School of Computing Science, http://homepages.cs.ncl.ac.uk/phillip.lord Room 914 Claremont Tower, skype: russet_apples Newcastle University, twitter: phillord NE1 7RU -- 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: Immutable or Effectively Immutable?
Yep. PersistentVector is *mutable* per the JCIP definition. If it is *mutable* then you need to use locks or synchronization to access its contents. If your program doesn't modify its the vector, it is *effectively immutable. *But, you need to ensure that you safely publish it. But, if you create a PersistentVector, and somehow ensure that the array's contents are never modified, you can pass it freely between threads without synchronization. In short, even though you can't claim that PersistentVector is *immutable*, if you discipline yourself on how you use it, you can pretend that it is. This is a consequence of the use of final on the array field in PersistentVector. On Wednesday, May 7, 2014 10:17:38 AM UTC-4, Andy Fingerhut wrote: Mike, I believe I understand the definition of truly immutable you are using here, and what it means in the JVM as far as synchronization of object values across threads. What seems a bit odd is to use the phrase truly immutable to describe something that is clearly mutable, or at least it is by the definition of mutable: can be modified after construction, which PersistentVector and others can be. Thanks, Andy On Tue, May 6, 2014 at 6:20 PM, Mike Fikes mike...@me.com javascript:wrote: Hi Andy, Marking Java fields as final has semantics with respect to threading, defined in the JLS in section 17.5 ( http://docs.oracle.com/javase/specs/jls/se5.0/html/memory.html#17.5) If you do this, then it makes it possible to freely pass a truly immutable object instance to another thread and be guaranteed that that other thread will see the value initialized for that field in the constructor. If you don't do this, then the object can still be effectively immutable, which essentially means that you can pass the object to another thread, so long as you do it in a safe manner (using a volatile, or some synchronization mechanism). JCIP helps clarify all of this unfortunately complex topic. The important thing (and key to Closure), is that, if you are implementing the class that you want to be immutable, then if you can mark everything as final, then you truly achieve the benefits immutability give you with concurrency (in short, you need no synchronization whatsoever). If you fail to do this, then you have effective immutability, which is good, but complex and comes with caveats on how you can safely pass objects between threads. JCIP is a great book. But, the approach taken by Clojure makes a lot of the complicated concerns covered by the book largely ignorable, IMHO. On Tuesday, May 6, 2014 8:35:43 PM UTC-4, Andy Fingerhut wrote: Alex, I may be unfamiliar with the definitions of truly immutable and effectively immutable being used here, but if I can mutate the contents of a Java Object array that is a final field after an object is constructed, does it really matter that much if it is final? It is trivially easy to mutate using Java access. Here is the example that I mentioned earlier in this thread, copied here for convenience: user= (def v [1 2 3]) #'user/v user= (class v) clojure.lang.PersistentVector user= v [1 2 3] user= (aset (.tail v) 1 -2) -2 user= v [1 -2 3] Andy On Tue, May 6, 2014 at 4:49 PM, Alex Miller al...@puredanger.comwrote: The Clojure persistent data structures are truly immutable - all fields are final and referred objects are not mutated after construction so that freeze occurs. One obvious exception are the transient variants ( http://clojure.org/transients). You can look at the code in https://github.com/clojure/clojure/tree/master/src/jvm/clojure/lang - any of the Persistent*.java. On Tuesday, May 6, 2014 4:11:49 PM UTC-5, Mike Fikes wrote: Are the persistent immutable data structures in Clojure truly immutable (using final fields, relying on constructor freezing), or are they mean to be merely effectively immutable (as defined in JICP)? -- 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 clo...@googlegroups.comjavascript: 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
Re: Immutable or Effectively Immutable?
I would offer that the key distinction is whether final is used: This prescribes what you must do when using the object. Take Date for example. You can't just pass one directly from one thread to another. The receiving thread could read a date associated with System.currentTimeMillis() of 0. But, String, since it uses final on its char[], fundamentally changes this. (If the final keyword were not present in String, even though you have no way to change its char[], it would be broken with respect to threading semantics.) On Wednesday, May 7, 2014 10:35:04 AM UTC-4, Andy Fingerhut wrote: Sorry if I'm beating a dead horse here. I agree that my example is not using published Clojure APIs, and I never do that kind of thing in a Clojure program, except as an example that PersistentVector's are mutable if you use Java APIs instead of restricting yourself to Clojure APIs. You don't even need to use reflection in Java or know about JVM security policies to mutate them (I am not suggesting that Clojure should be changed in any way here). I've actually got a copy of Java: Concurrency in Practice, and looked up (some of) what they say about immutability. Here is one definition they give of immutability, with some preceding text. I have added emphasis to one phrase: Neither the Java Language Specification nor the Java Memory Model formally defines immutability, but __immutability is *not* equivalent to simply declaring all fields of an object 'final'__. An object whose fields are all final may still be mutable, since final fields can hold references to mutable objects. An object is *immutable* if: + Its state cannot be modified after construction; + All its fields are 'final'; and + It is *properly constructed* (the 'this' reference does not escape during construction). I have no argument with PersistentVector satisfying the 2nd and 3rd bullet points above, but (1) seems not to hold. According to JCIP's definition of effectively immutable (Objects that are not technically immutable, but whose state will not be modified after publication), PersistentVector appears to me to be effectively immutable, but not truly immutable. Andy On Tue, May 6, 2014 at 8:31 PM, Alex Miller al...@puredanger.comjavascript: wrote: Hey Andy, It does matter with regard to visibility across threads - your example does not use a synchronization mechanism and there is no guarantee that other threads will ever see those changes (so don't ever ever do that :). But if you stick to the normal Clojure apis, all is good. I'd highly recommend reading JCIP to dive into the details. Final field freeze is particularly weird and it baked my noodle when I first encountered it - here's a blog I wrote about it approx 697 years ago in internet time (and Brian Goetz backs me up in the comments :) http://tech.puredanger.com/2008/11/26/jmm-and-final-field-freeze/ Alex On Tuesday, May 6, 2014 7:35:43 PM UTC-5, Andy Fingerhut wrote: Alex, I may be unfamiliar with the definitions of truly immutable and effectively immutable being used here, but if I can mutate the contents of a Java Object array that is a final field after an object is constructed, does it really matter that much if it is final? It is trivially easy to mutate using Java access. Here is the example that I mentioned earlier in this thread, copied here for convenience: user= (def v [1 2 3]) #'user/v user= (class v) clojure.lang.PersistentVector user= v [1 2 3] user= (aset (.tail v) 1 -2) -2 user= v [1 -2 3] Andy On Tue, May 6, 2014 at 4:49 PM, Alex Miller al...@puredanger.comwrote: The Clojure persistent data structures are truly immutable - all fields are final and referred objects are not mutated after construction so that freeze occurs. One obvious exception are the transient variants ( http://clojure.org/transients). You can look at the code in https://github.com/clojure/clojure/tree/master/src/jvm/clojure/lang - any of the Persistent*.java. On Tuesday, May 6, 2014 4:11:49 PM UTC-5, Mike Fikes wrote: Are the persistent immutable data structures in Clojure truly immutable (using final fields, relying on constructor freezing), or are they mean to be merely effectively immutable (as defined in JICP)? -- 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
Immutable or Effectively Immutable?
Are the persistent immutable data structures in Clojure truly immutable (using final fields, relying on constructor freezing), or are they mean to be merely effectively immutable (as defined in JICP)? -- 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: Immutable or Effectively Immutable?
I haven't read JICP that you refer to, but I believe that they are effectively immutable. See a post by me in this thread titled Clojure Concurrency and Custom Types from March 2013 for how to stay within Clojure, but I believe requiring Java interop calls, to mutate in place Clojure's immutable data structures: https://mail.google.com/mail/u/0/#search/label%3Aclojure+concurrency+and+custom+types/13d9d40bc9dd658a I have never seen code like that in any Clojure libraries I have looked at, though. Andy On Tue, May 6, 2014 at 2:11 PM, Mike Fikes mikefi...@me.com wrote: Are the persistent immutable data structures in Clojure truly immutable (using final fields, relying on constructor freezing), or are they mean to be merely effectively immutable (as defined in JICP)? -- 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: Immutable or Effectively Immutable?
The Clojure persistent data structures are truly immutable - all fields are final and referred objects are not mutated after construction so that freeze occurs. One obvious exception are the transient variants (http://clojure.org/transients). You can look at the code in https://github.com/clojure/clojure/tree/master/src/jvm/clojure/lang - any of the Persistent*.java. On Tuesday, May 6, 2014 4:11:49 PM UTC-5, Mike Fikes wrote: Are the persistent immutable data structures in Clojure truly immutable (using final fields, relying on constructor freezing), or are they mean to be merely effectively immutable (as defined in JICP)? -- 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: Immutable or Effectively Immutable?
And hash codes are not final as they are calculated on-the-fly on most of the Clojure data structures. Timothy On Tue, May 6, 2014 at 5:49 PM, Alex Miller a...@puredanger.com wrote: The Clojure persistent data structures are truly immutable - all fields are final and referred objects are not mutated after construction so that freeze occurs. One obvious exception are the transient variants ( http://clojure.org/transients). You can look at the code in https://github.com/clojure/clojure/tree/master/src/jvm/clojure/lang - any of the Persistent*.java. On Tuesday, May 6, 2014 4:11:49 PM UTC-5, Mike Fikes wrote: Are the persistent immutable data structures in Clojure truly immutable (using final fields, relying on constructor freezing), or are they mean to be merely effectively immutable (as defined in JICP)? -- 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. -- “One of the main causes of the fall of the Roman Empire was that–lacking zero–they had no way to indicate successful termination of their C programs.” (Robert Firth) -- 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: Immutable or Effectively Immutable?
Alex, I may be unfamiliar with the definitions of truly immutable and effectively immutable being used here, but if I can mutate the contents of a Java Object array that is a final field after an object is constructed, does it really matter that much if it is final? It is trivially easy to mutate using Java access. Here is the example that I mentioned earlier in this thread, copied here for convenience: user= (def v [1 2 3]) #'user/v user= (class v) clojure.lang.PersistentVector user= v [1 2 3] user= (aset (.tail v) 1 -2) -2 user= v [1 -2 3] Andy On Tue, May 6, 2014 at 4:49 PM, Alex Miller a...@puredanger.com wrote: The Clojure persistent data structures are truly immutable - all fields are final and referred objects are not mutated after construction so that freeze occurs. One obvious exception are the transient variants ( http://clojure.org/transients). You can look at the code in https://github.com/clojure/clojure/tree/master/src/jvm/clojure/lang - any of the Persistent*.java. On Tuesday, May 6, 2014 4:11:49 PM UTC-5, Mike Fikes wrote: Are the persistent immutable data structures in Clojure truly immutable (using final fields, relying on constructor freezing), or are they mean to be merely effectively immutable (as defined in JICP)? -- 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: Immutable or Effectively Immutable?
vec with a short array of objects is a special case in that it simply puts the existing array in a PersistentVector wrapper: user= (def arr (object-array 16)) #'user/arr user= (doseq [i (range 16)] (aset arr i i)) nil user= (def v (vec arr)) #'user/v user= v [0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15] user= (aset arr 0 :foo) :foo user= v [:foo 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15] This works for up to 32 objects, as that is the number that fits in a PV tail. No member access syntax here -- not sure if object-array/aset count as interop. NB. vec's docstring is explicit about this. On 7 May 2014 02:35, Andy Fingerhut andy.finger...@gmail.com wrote: Alex, I may be unfamiliar with the definitions of truly immutable and effectively immutable being used here, but if I can mutate the contents of a Java Object array that is a final field after an object is constructed, does it really matter that much if it is final? It is trivially easy to mutate using Java access. Here is the example that I mentioned earlier in this thread, copied here for convenience: user= (def v [1 2 3]) #'user/v user= (class v) clojure.lang.PersistentVector user= v [1 2 3] user= (aset (.tail v) 1 -2) -2 user= v [1 -2 3] Andy On Tue, May 6, 2014 at 4:49 PM, Alex Miller a...@puredanger.com wrote: The Clojure persistent data structures are truly immutable - all fields are final and referred objects are not mutated after construction so that freeze occurs. One obvious exception are the transient variants (http://clojure.org/transients). You can look at the code in https://github.com/clojure/clojure/tree/master/src/jvm/clojure/lang - any of the Persistent*.java. On Tuesday, May 6, 2014 4:11:49 PM UTC-5, Mike Fikes wrote: Are the persistent immutable data structures in Clojure truly immutable (using final fields, relying on constructor freezing), or are they mean to be merely effectively immutable (as defined in JICP)? -- 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. -- 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: Immutable or Effectively Immutable?
Hi Andy, Marking Java fields as final has semantics with respect to threading, defined in the JLS in section 17.5 (http://docs.oracle.com/javase/specs/jls/se5.0/html/memory.html#17.5) If you do this, then it makes it possible to freely pass a truly immutable object instance to another thread and be guaranteed that that other thread will see the value initialized for that field in the constructor. If you don't do this, then the object can still be effectively immutable, which essentially means that you can pass the object to another thread, so long as you do it in a safe manner (using a volatile, or some synchronization mechanism). JCIP helps clarify all of this unfortunately complex topic. The important thing (and key to Closure), is that, if you are implementing the class that you want to be immutable, then if you can mark everything as final, then you truly achieve the benefits immutability give you with concurrency (in short, you need no synchronization whatsoever). If you fail to do this, then you have effective immutability, which is good, but complex and comes with caveats on how you can safely pass objects between threads. JCIP is a great book. But, the approach taken by Clojure makes a lot of the complicated concerns covered by the book largely ignorable, IMHO. On Tuesday, May 6, 2014 8:35:43 PM UTC-4, Andy Fingerhut wrote: Alex, I may be unfamiliar with the definitions of truly immutable and effectively immutable being used here, but if I can mutate the contents of a Java Object array that is a final field after an object is constructed, does it really matter that much if it is final? It is trivially easy to mutate using Java access. Here is the example that I mentioned earlier in this thread, copied here for convenience: user= (def v [1 2 3]) #'user/v user= (class v) clojure.lang.PersistentVector user= v [1 2 3] user= (aset (.tail v) 1 -2) -2 user= v [1 -2 3] Andy On Tue, May 6, 2014 at 4:49 PM, Alex Miller al...@puredanger.comjavascript: wrote: The Clojure persistent data structures are truly immutable - all fields are final and referred objects are not mutated after construction so that freeze occurs. One obvious exception are the transient variants ( http://clojure.org/transients). You can look at the code in https://github.com/clojure/clojure/tree/master/src/jvm/clojure/lang - any of the Persistent*.java. On Tuesday, May 6, 2014 4:11:49 PM UTC-5, Mike Fikes wrote: Are the persistent immutable data structures in Clojure truly immutable (using final fields, relying on constructor freezing), or are they mean to be merely effectively immutable (as defined in JICP)? -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clo...@googlegroups.comjavascript: 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 javascript: 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 javascript:. 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: Immutable or Effectively Immutable?
Thanks! I initially saw that the count field of ArrayNode (in PersistentHashMap) is non-final and also mutated in at least one case, and began to question things. But, for that particular example, if that field is only mutated in the case of editing transients, then for the non-transient case ArrayNode is effectively immutable but also safely published by any truly immutable data structures by being referred to in final fields. Excellent! I had to look for myself, and now I feel much more comfortable that Clojure is built upon the bedrock it needs to be :) On Tuesday, May 6, 2014 7:49:07 PM UTC-4, Alex Miller wrote: The Clojure persistent data structures are truly immutable - all fields are final and referred objects are not mutated after construction so that freeze occurs. One obvious exception are the transient variants ( http://clojure.org/transients). You can look at the code in https://github.com/clojure/clojure/tree/master/src/jvm/clojure/lang - any of the Persistent*.java. On Tuesday, May 6, 2014 4:11:49 PM UTC-5, Mike Fikes wrote: Are the persistent immutable data structures in Clojure truly immutable (using final fields, relying on constructor freezing), or are they mean to be merely effectively immutable (as defined in JICP)? -- 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: Immutable or Effectively Immutable?
Yes, there may be a few special cases out there, but largely around transients. The transient case constrains the mutability to a thread so still simplifies the concurrency safety story immensely. On Tuesday, May 6, 2014 8:44:53 PM UTC-5, Mike Fikes wrote: Thanks! I initially saw that the count field of ArrayNode (in PersistentHashMap) is non-final and also mutated in at least one case, and began to question things. But, for that particular example, if that field is only mutated in the case of editing transients, then for the non-transient case ArrayNode is effectively immutable but also safely published by any truly immutable data structures by being referred to in final fields. Excellent! I had to look for myself, and now I feel much more comfortable that Clojure is built upon the bedrock it needs to be :) On Tuesday, May 6, 2014 7:49:07 PM UTC-4, Alex Miller wrote: The Clojure persistent data structures are truly immutable - all fields are final and referred objects are not mutated after construction so that freeze occurs. One obvious exception are the transient variants ( http://clojure.org/transients). You can look at the code in https://github.com/clojure/clojure/tree/master/src/jvm/clojure/lang - any of the Persistent*.java. On Tuesday, May 6, 2014 4:11:49 PM UTC-5, Mike Fikes wrote: Are the persistent immutable data structures in Clojure truly immutable (using final fields, relying on constructor freezing), or are they mean to be merely effectively immutable (as defined in JICP)? -- 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: Immutable or Effectively Immutable?
Hey Andy, It does matter with regard to visibility across threads - your example does not use a synchronization mechanism and there is no guarantee that other threads will ever see those changes (so don't ever ever do that :). But if you stick to the normal Clojure apis, all is good. I'd highly recommend reading JCIP to dive into the details. Final field freeze is particularly weird and it baked my noodle when I first encountered it - here's a blog I wrote about it approx 697 years ago in internet time (and Brian Goetz backs me up in the comments :) http://tech.puredanger.com/2008/11/26/jmm-and-final-field-freeze/ Alex On Tuesday, May 6, 2014 7:35:43 PM UTC-5, Andy Fingerhut wrote: Alex, I may be unfamiliar with the definitions of truly immutable and effectively immutable being used here, but if I can mutate the contents of a Java Object array that is a final field after an object is constructed, does it really matter that much if it is final? It is trivially easy to mutate using Java access. Here is the example that I mentioned earlier in this thread, copied here for convenience: user= (def v [1 2 3]) #'user/v user= (class v) clojure.lang.PersistentVector user= v [1 2 3] user= (aset (.tail v) 1 -2) -2 user= v [1 -2 3] Andy On Tue, May 6, 2014 at 4:49 PM, Alex Miller al...@puredanger.comjavascript: wrote: The Clojure persistent data structures are truly immutable - all fields are final and referred objects are not mutated after construction so that freeze occurs. One obvious exception are the transient variants ( http://clojure.org/transients). You can look at the code in https://github.com/clojure/clojure/tree/master/src/jvm/clojure/lang - any of the Persistent*.java. On Tuesday, May 6, 2014 4:11:49 PM UTC-5, Mike Fikes wrote: Are the persistent immutable data structures in Clojure truly immutable (using final fields, relying on constructor freezing), or are they mean to be merely effectively immutable (as defined in JICP)? -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clo...@googlegroups.comjavascript: 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 javascript: 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 javascript:. 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: Immutable or Effectively Immutable?
True! Hash codes are a special case - the pattern they use is sometimes called the racy single-check idiom and is discussed in Effective Java in Item 71 or on an internet near you. The canonical example of this is java.lang.String. The trick is that if you don't have a non-0 hash code, compute it yourself and stash it. If threads happen to see it, they can use it! If they don't see it, they compute it themselves. If two threads race, they write the *same* value, so everyone is fine. One important aspect is that the hash code must be an int which can be written atomically; if it was a long, you'd potentially be subject to long tearing. As of Clojure 1.6, Symbols also use this idiom for hasheq. Keywords do not - the assumption with keywords is that they are likely to be used as keys and so the hasheq is pre-computed and cached during construction (but keywords are re-used so this is only done once per keyword). On Tuesday, May 6, 2014 7:07:37 PM UTC-5, tbc++ wrote: And hash codes are not final as they are calculated on-the-fly on most of the Clojure data structures. Timothy On Tue, May 6, 2014 at 5:49 PM, Alex Miller al...@puredanger.comjavascript: wrote: The Clojure persistent data structures are truly immutable - all fields are final and referred objects are not mutated after construction so that freeze occurs. One obvious exception are the transient variants ( http://clojure.org/transients). You can look at the code in https://github.com/clojure/clojure/tree/master/src/jvm/clojure/lang - any of the Persistent*.java. On Tuesday, May 6, 2014 4:11:49 PM UTC-5, Mike Fikes wrote: Are the persistent immutable data structures in Clojure truly immutable (using final fields, relying on constructor freezing), or are they mean to be merely effectively immutable (as defined in JICP)? -- You received this message because you are subscribed to the Google Groups Clojure group. To post to this group, send email to clo...@googlegroups.comjavascript: 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 javascript: 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 javascript:. For more options, visit https://groups.google.com/d/optout. -- “One of the main causes of the fall of the Roman Empire was that–lacking zero–they had no way to indicate successful termination of their C programs.” (Robert Firth) -- 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.