From rssh at gradsoft.com.ua Tue Jun 2 01:17:57 2009 From: rssh at gradsoft.com.ua (Ruslan Shevchenko) Date: Tue, 2 Jun 2009 11:17:57 +0300 (EEST) Subject: statistics for selected set of proposals. Message-ID: <2d1e8775ed8124a27427e2db76010921.squirrel@wmail.gradsoft.ua> Good day, community. Number of entries in different lines (if suitable), and percentage between other simular language constructs (if suitable): openjdk-jdk: CollectionGetOrSet (simplicified collection element access): 5438 CollectionLiterals (collection literals can be applied): 35 DiamondInitializers (initializers with allocation and type arguments): 1499 DiamondInitializers_percents (per all variable initializers): 1.071503 Elvis (Elvis and Other Null-Safe Operators): 821 Elvis_percents (per if-s and conditions): 2.330136 MultiCatch (multi catch): 412 MultiCatch_percents (per all catchs): 4.898347 NewIntegerLiterals (New Integer Literals): 7131 NewIntegerLiterals_percents (per all integer literal): 5.848821 StringInSwitch (string in switch): 444 compiere ERP: CollectionGetOrSet (simplicified collection element access): 732 CollectionLiterals (collection literals can be applied): 5 DiamondInitializers (initializers with allocation and type arguments): 708 DiamondInitializers_percents (per all variable initializers): 2.281884 Elvis (Elvis and Other Null-Safe Operators): 67 Elvis_percents (per if-s and conditions): 1.016229 MultiCatch (multi catch): 7 MultiCatch_percents (per all catchs): 0.310973 NewIntegerLiterals (New Integer Literals): 1424 NewIntegerLiterals_percents (per all integer literal): 6.333956 StringInSwitch (string in switch): 215 jetty: CollectionGetOrSet (simplicified collection element access): 241 CollectionLiterals (collection literals can be applied): 1 DiamondInitializers (initializers with allocation and type arguments): 0 DiamondInitializers_percents (per all variable initializers): 0 Elvis (Elvis and Other Null-Safe Operators): 68 Elvis_percents (per if-s and conditions): 6.532181 MultiCatch (multi catch): 22 MultiCatch_percents (per all catchs): 7.829181 NewIntegerLiterals (New Integer Literals): 87 NewIntegerLiterals_percents (per all integer literal): 2.996900 StringInSwitch (string in switch): 19 hibernate: CollectionGetOrSet (simplicified collection element access): 418 CollectionLiterals (collection literals can be applied): 9 DiamondInitializers (initializers with allocation and type arguments): 100 DiamondInitializers_percents (per all variable initializers): 0.973615 Elvis (Elvis and Other Null-Safe Operators): 193 Elvis_percents (per if-s and conditions): 6.027483 MultiCatch (multi catch): 25 MultiCatch_percents (per all catchs): 3.846154 NewIntegerLiterals (New Integer Literals): 13 NewIntegerLiterals_percents (per all integer literal): 0.401235 StringInSwitch (string in switch): 86 gwt-user: CollectionGetOrSet (simplicified collection element access): 324 CollectionLiterals (collection literals can be applied): 6 DiamondInitializers (initializers with allocation and type arguments): 252 DiamondInitializers_percents (per all variable initializers): 5.988593 Elvis (Elvis and Other Null-Safe Operators): 28 Elvis_percents (per if-s and conditions): 2.969247 MultiCatch (multi catch): 9 MultiCatch_percents (per all catchs): 5.263158 NewIntegerLiterals (New Integer Literals): 26 NewIntegerLiterals_percents (per all integer literal): 1.139351 StringInSwitch (string in switch): 10 If you want run on own set of data or modify checks and calculations, then get 2.5.0p6 from http://datacenter.gradsoft.ua/public.repository/ua.gradsoft/javachecker/installations/JavaCheckerSourceInstaller-2.5.0p6.jar than as described in my first letter. // NewInteger is sum of bytes + widening (?) + big literals. // Elvis - sub of elvis and null-safe. // CollectionLiterals: when we see 2 or bigger put(x,y) where x and y are constants, or 2 or bigger add(constant) or Arrays.asList(constants...) Regards ! From rssh at gradsoft.com.ua Tue Jun 2 02:16:45 2009 From: rssh at gradsoft.com.ua (Ruslan Shevchenko) Date: Tue, 2 Jun 2009 12:16:45 +0300 (EEST) Subject: For further consideration, round 2 Message-ID: Good day. Some random notes about including/excluding proposal to/from final draft. Of course, from my part of elephant. // Knowing, that my and Joe Darcy opinions usually opposite, you can // inverse my suggestions and receive final results ;) 1. Logically a combined proposal for better integral literals: Including this to final draft will make changes to language hightly alogical: if integers than why not strings ? One difference - that for strings we have group of users (database developers), for which live without new strings is a big pain; for integers - not. But reverse usability looks strange to be acceptable criteria. So, my vote - does not include new integer literals. 2. Improved Type Inference for Generic Instance Creation. Ohh. Sorry, but I must say, that choosing such variant of limited type inference over 'auto' proposal will speed-up process of switching developers from java to less verbose languages: java become not 'archaic because infrequently updated', but 'archaic by design'. >From other side - this is better than nothing. So, better include. 3. Language support for JSR 292. Must be. (Also, with reasons from previous item, main value of Java will be 'good JVM C/assembler') 4. Automatic Resource Management. Must be. 5. Large arrays. Knowing (3): better include. 6,7 (Elvis and Other Null-Safe Operators, Indexing access syntax for Lists and Maps) I have no special opinion. I. e. including or excluding such proposal, I think, globally will change nothing. 8,9, Strings in switch, Collection Literals. In principle the same as (6,7) but effects from those proposal is less then listed for previous items. 10. Simplified Varargs Method Invocation. I guess this is 'maintance-like' proposal. Better include. That's all. Regards ! From jl0235 at yahoo.com Tue Jun 2 05:59:40 2009 From: jl0235 at yahoo.com (james lowden) Date: Tue, 2 Jun 2009 05:59:40 -0700 (PDT) Subject: 64-bit array functionality implemented via libraries? Message-ID: <525909.10390.qm@web63707.mail.re1.yahoo.com> My preference for doing something like this would be to introducted a parallel LargeList/LargeCollection interface that used 64-bit indexing but otherwise shared semantics with the extant List/Collection interfaces, and have the [] access work for either, and then do the large array via a "LargeArrayList" (or something) implementation of the large list, probably represented internally as an array-of-arrays. I'll toss something together at some point. . . --- On Thu, 5/28/09, Mark Thornton wrote: > From: Mark Thornton > Subject: Re: 64-bit array functionality implemented via libraries? > To: "Joe Darcy" , coin-dev at openjdk.java.net > Date: Thursday, May 28, 2009, 3:35 PM > Joe Darcy wrote: > > Hello. > > > > As another point in the design space, assuming > indexing access syntax is > > available for user-defined types and the existence of > collection > > literals, I'd like to see what implementing 64-bit > array functionality > > via libraries would look like. > >??? > Not quite sure what you are looking for here as the public > interface > seems fairly obvious apart from minor details. > > public abstract class LargeArray LargeArray> implements > Cloneable, Serializable { > ? ? public final long length; > ? ? protected LargeArray(long length) {...} > ? ? public T clone(); > } > > public class LargeObjectArray extends > LargeArray> { > ? ? public LargeObjectArray(long length) {...} > ? ? public E get(long index) {...} > ? ? public void set(long index, E value) {...} > } > > public class LargeIntArray extends > LargeArray { > ? ? public LargeIntArray(long length) {...} > ? ? public int get(long index) {...} > ? ? public void set(long index, int value) {...} > } > > // etc for the other primitives > > However this can only be used with the proposed [] access, > if that is > not based on the existing List/Collection interfaces as > they have > integer rather than long size and index types. > > Mark Thornton > > > From mthornton at optrak.co.uk Tue Jun 2 06:30:19 2009 From: mthornton at optrak.co.uk (Mark Thornton) Date: Tue, 02 Jun 2009 14:30:19 +0100 Subject: 64-bit array functionality implemented via libraries? In-Reply-To: <525909.10390.qm@web63707.mail.re1.yahoo.com> References: <525909.10390.qm@web63707.mail.re1.yahoo.com> Message-ID: <4A25296B.3040601@optrak.co.uk> james lowden wrote: > My preference for doing something like this would be to introducted a parallel LargeList/LargeCollection interface that used 64-bit indexing but otherwise shared semantics with the extant List/Collection interfaces, and have the [] access work for either, and then do the large array via a "LargeArrayList" (or something) implementation of the large list, probably represented internally as an array-of-arrays. I'll toss something together at some point. . . > Large collections raise additional issues of use cases and performance expectations that don't arise with a simple large array. For example consider inserting near the front of a 4 billion element array list. Mark Thornton From jl0235 at yahoo.com Tue Jun 2 08:30:55 2009 From: jl0235 at yahoo.com (james lowden) Date: Tue, 2 Jun 2009 08:30:55 -0700 (PDT) Subject: 64-bit array functionality implemented via libraries? Message-ID: <631055.52469.qm@web63701.mail.re1.yahoo.com> My perspective on that is that's more an issue of picking the correct data structure for the task at hand--if you're planning to insert at the beginning frequently, an ArrayList is likely not the best choice of collection anyway. --- On Tue, 6/2/09, Mark Thornton wrote: > From: Mark Thornton > Subject: Re: 64-bit array functionality implemented via libraries? > To: "james lowden" > Cc: coin-dev at openjdk.java.net > Date: Tuesday, June 2, 2009, 8:30 AM > james lowden wrote: > > My preference for doing something like this would be > to introducted a parallel LargeList/LargeCollection > interface that used 64-bit indexing but otherwise shared > semantics with the extant List/Collection interfaces, and > have the [] access work for either, and then do the large > array via a "LargeArrayList" (or something) implementation > of the large list, probably represented internally as an > array-of-arrays.? I'll toss something together at some > point. . . > >??? > Large collections raise additional issues of use cases and > performance expectations that don't arise with a simple > large array. For example consider inserting near the front > of a 4 billion element array list. > > Mark Thornton > > From reinier at zwitserloot.com Tue Jun 2 08:32:27 2009 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Tue, 2 Jun 2009 17:32:27 +0200 Subject: 64-bit array functionality implemented via libraries? In-Reply-To: <4A25296B.3040601@optrak.co.uk> References: <525909.10390.qm@web63707.mail.re1.yahoo.com> <4A25296B.3040601@optrak.co.uk> Message-ID: <532E1B55-24AA-48E6-85F8-3C22F51EF4C3@zwitserloot.com> There is no expectation that inserting near the front of a large list is going to be performant when employing an enormous list. More to the point, whereas with arrays you're in the same boat, and the only 'benefit', is that arrays are so inflexible that it's not only more obvious this is going to be very slow, it also causes more boilerplate if for whatever reason you want to do this anyway - with an interface you can use an implementation that supports much faster near-front insertions. Wouldn't it be far more fruitful for the javac/JVM core time to figure out how to make primitive generics work properly? With such a construct, arrays can truly be relegated to a niche, and ArrayList would be as fast as byte[], and require about the same order of memory, instead of 9 to 17 times more depending on JVM. Such a change undoubtedly means it can't be java.util.List, but instead a new collections API, so while the opportunity is there, support for primitives in generics is quite easy: Let a generics parameter declaration explicitly mention that it supports primitives as well as classes. Once you have the freedom of not being tied to retrofitting existing classes, it's doable. Before someone claims this is utterly impossible, various languages have managed it before. Here's a layout of one strategy to make this work in java: Not just any generics can take primitives; only those explicitly marked as such, like so: package java.nutil; //new util - not compatible with old util's List. public interface List { public T get(long idx); public long size(); } such generics classes always carry the raw type of their T as a Class reference in each instance. That is, an instance List> knows it's a List of Lists, but not what kind of Lists, but the inner Lists know they are a list of strings. A List is perfectly legal, and the inner type would then be 'int.class' (which is different from Integer.class). Internally, for each mention of 'T', all variants are generated. The above 'get(long idx)', therefore, translates to many methods: Object(long idx), int(long idx), short(long idx), etcetera. Similarly, an .add(T x) method would expand to many methods; add(Object), add(int), add(boolean), etc. If compile time integrity of the generics is assured (that is - there were no generics warnings), then a call to an .add() method will always result in either calling add(int), or add(Object), with an instance of java.lang.Integer. These can be trivially channeled towards the same, 'T' accepting method. When integrity is compromised, the internal reference to the raw type ensures a ClassCastException can be generated appropriately. null assignments are allowed but can result in NPEs if the 'T' happens to be a primitive. Because 'null' is not part of java's type system, this can't be (easily) fixed. Regrettable, but certainly nothing new; auto- unboxing suffers from the same flaw. Any 'T' typed variables are just like now, Objects; even a List that holds a 'private T foo;' field would use java.lang.Integer and not 'int'. However, creating arrays is allowed, via a special utility class. (Possible here, unlike java1.5 generics, because of the internal reference to the raw type). Thus, code that looks like this: NewList list = FastList.create(); list.add(10); would boil down to: Create a new instance of FastList. store 'int.class' somewhere inside it. list.add(10); - on a non-hotspotted run, the add(int) method will first check that this is a list of int.class or Integer.class and delegate to the right method. If not, a CCE is generated. During a hotspot run, hotspot would ascertain that this is a pointless check, and skip it entirely; link the .add() call straight to the right code that actually works with a primitive int. My point isn't so much that this mail is a complete proposal for such a system (it certainly isn't, and, indeed, I doubt such a proposal would be even close to small enough to fit within Project Coin's mission), but rather that jumping through hoops changing the language itself seems short-sighted to me. The value of a long arrays proposal (vs. just using libraries to do it) exists only because java currently lacks something that is fixable and would have far more utility. --Reinier Zwitserloot On 02-06-2009, at 15:30, Mark Thornton wrote: > james lowden wrote: >> My preference for doing something like this would be to introducted >> a parallel LargeList/LargeCollection interface that used 64-bit >> indexing but otherwise shared semantics with the extant List/ >> Collection interfaces, and have the [] access work for either, and >> then do the large array via a "LargeArrayList" (or something) >> implementation of the large list, probably represented internally >> as an array-of-arrays. I'll toss something together at some >> point. . . >> > Large collections raise additional issues of use cases and performance > expectations that don't arise with a simple large array. For example > consider inserting near the front of a 4 billion element array list. > > Mark Thornton > > From neal at gafter.com Tue Jun 2 08:37:52 2009 From: neal at gafter.com (Neal Gafter) Date: Tue, 2 Jun 2009 08:37:52 -0700 Subject: 64-bit array functionality implemented via libraries? In-Reply-To: <532E1B55-24AA-48E6-85F8-3C22F51EF4C3@zwitserloot.com> References: <525909.10390.qm@web63707.mail.re1.yahoo.com> <4A25296B.3040601@optrak.co.uk> <532E1B55-24AA-48E6-85F8-3C22F51EF4C3@zwitserloot.com> Message-ID: <15e8b9d20906020837ud47805x6e5a171f0e2aa535@mail.gmail.com> On Tue, Jun 2, 2009 at 8:32 AM, Reinier Zwitserloot wrote: > Wouldn't it be far more fruitful for the javac/JVM core time to figure > out how to make primitive generics work properly? More fruitful? Sure, at the cost of an order of magnitude (or two) more work. From mthornton at optrak.co.uk Tue Jun 2 08:53:50 2009 From: mthornton at optrak.co.uk (Mark Thornton) Date: Tue, 02 Jun 2009 16:53:50 +0100 Subject: 64-bit array functionality implemented via libraries? In-Reply-To: <532E1B55-24AA-48E6-85F8-3C22F51EF4C3@zwitserloot.com> References: <525909.10390.qm@web63707.mail.re1.yahoo.com> <4A25296B.3040601@optrak.co.uk> <532E1B55-24AA-48E6-85F8-3C22F51EF4C3@zwitserloot.com> Message-ID: <4A254B0E.4010303@optrak.co.uk> Reinier Zwitserloot wrote: > There is no expectation that inserting near the front of a large list > is going to be performant when employing an enormous list. Some types of lists do support fast insertion anywhere. I question whether a large collection library should include a LargeArrayList at all. > Wouldn't it be far more fruitful for the javac/JVM core time to figure > out how to make primitive generics work properly? With such a > construct, arrays can truly be relegated to a niche, and > ArrayList would be as fast as byte[], and require about the same > order of memory, instead of 9 to 17 times more depending on JVM. Such > a change undoubtedly means it can't be java.util.List, but instead a > new collections API, so while the opportunity is there, support for > primitives in generics is quite easy: Let a generics parameter > declaration explicitly mention that it supports primitives as well as > classes. Once you have the freedom of not being tied to retrofitting > existing classes, it's doable. While it would be nice I came to the conclusion that this really ought to be done in the context of reifying generics. Otherwise you add the additional wart of generics involving primitives being (necessarily) reified while those involving Objects are not. > > Internally, for each mention of 'T', all variants are generated. The > above 'get(long idx)', therefore, translates to many methods: > Object(long idx), int(long idx), short(long idx), etcetera. Similarly, > an .add(T x) method would expand to many methods; add(Object), > add(int), add(boolean), etc. Better to generate the variants on demand at runtime. > > My point isn't so much that this mail is a complete proposal for such > a system (it certainly isn't, and, indeed, I doubt such a proposal > would be even close to small enough to fit within Project Coin's > mission), but rather that jumping through hoops changing the language > itself seems short-sighted to me. The value of a long arrays proposal > (vs. just using libraries to do it) exists only because java currently > lacks something that is fixable and would have far more utility. > It seems that large arrays and large collections raise a whole host of issues which we can barely begin to consider in the scope of Coin. If we want to restrict [] to collections, then we aren't ready to define big collections. A more general approach that allowed [] for any class that had get/set marked (annotated?) in some way could be used to provide large arrays that might later be implemented in a different way. Regards, Mark From mthornton at optrak.co.uk Tue Jun 2 09:03:45 2009 From: mthornton at optrak.co.uk (Mark Thornton) Date: Tue, 02 Jun 2009 17:03:45 +0100 Subject: 64-bit array functionality implemented via libraries? In-Reply-To: <15e8b9d20906020837ud47805x6e5a171f0e2aa535@mail.gmail.com> References: <525909.10390.qm@web63707.mail.re1.yahoo.com> <4A25296B.3040601@optrak.co.uk> <532E1B55-24AA-48E6-85F8-3C22F51EF4C3@zwitserloot.com> <15e8b9d20906020837ud47805x6e5a171f0e2aa535@mail.gmail.com> Message-ID: <4A254D61.7030100@optrak.co.uk> Neal Gafter wrote: > On Tue, Jun 2, 2009 at 8:32 AM, Reinier Zwitserloot > > wrote: > > Wouldn't it be far more fruitful for the javac/JVM core time to figure > out how to make primitive generics work properly? > > > More fruitful? Sure, at the cost of an order of magnitude (or two) > more work. The Scala people are working on specialization to reduce the amount of boxing required with 'primitives' (aka value types) http://lamp.epfl.ch/~dragos/files/scala-spec.pdf If they get it to work, perhaps the more fruitful approach would be to use Scala for tasks where this is important and not try to get it into Java. Regards, Mark Thornton From neal at gafter.com Tue Jun 2 15:08:36 2009 From: neal at gafter.com (Neal Gafter) Date: Tue, 2 Jun 2009 15:08:36 -0700 Subject: 64-bit array functionality implemented via libraries? In-Reply-To: <4A254D61.7030100@optrak.co.uk> References: <525909.10390.qm@web63707.mail.re1.yahoo.com> <4A25296B.3040601@optrak.co.uk> <532E1B55-24AA-48E6-85F8-3C22F51EF4C3@zwitserloot.com> <15e8b9d20906020837ud47805x6e5a171f0e2aa535@mail.gmail.com> <4A254D61.7030100@optrak.co.uk> Message-ID: <15e8b9d20906021508u5b5c18c6wffea74e4ccd38d49@mail.gmail.com> On Tue, Jun 2, 2009 at 9:03 AM, Mark Thornton wrote: > The Scala people are working on specialization to reduce the amount of > boxing required with 'primitives' (aka value types) > > http://lamp.epfl.ch/~dragos/files/scala-spec.pdf > > If they get it to work, perhaps the more fruitful approach would be to use > Scala for tasks where this is important and not try to get it into Java. > That may be useful for greenfield projects that don't intend to use any existing Java APIs. Such projects are the minority. Java is worth improving no matter what happens with Scala. From John.Rose at Sun.COM Fri Jun 12 22:42:33 2009 From: John.Rose at Sun.COM (John Rose) Date: Fri, 12 Jun 2009 22:42:33 -0700 Subject: Points about language support for 292 In-Reply-To: References: Message-ID: <81C1AB19-7F1F-4061-96E9-2FB73CC39BAB@sun.com> Back to (the ever-contentious topic of) checked exceptions, w.r.t. JSR 292. Although I doubted at first, I now agree (with Alex, Neal, et al) that where JSR 292 punches into the JLS, it should not bring a new loophole in the static checking of throws and catches. I have converted the mlvm patches for javac and the JSR 292 runtime, and found in almost all cases that I had to put an annoying "throws Throwable" on various MethodHandles APIs and intermediate shim methods. Once done, it looks unappetizing, but so far the extra "throws" do not seem to impede using Java as a systems programming language for dynamic language implementations. (Also, some of you will like this news, I think the exercise turned up one potential bug, where checked exceptions from the bootstrap method would have mingled with the call site if not caught and wrapped properly; this would have been very confusing.) So I think the "look" of dynamic language implementation code in Java will include a fair number of "throws Throwable" to mollify Java's exception checking rules. Yet to be seen is what effect such blanket throwing will have on surrounding code. I am starting to reach for remedies like this: void foo() throws IOException { doSomeIO(); try { InvokeDynamic.foo(); } catch (Throwable ex) { throw checkedException(ex, IOException.class); } doSomeMoreIO(); } where, more or less: static T checkedException(Throwable t, Class tc) throws Error, RuntimeException { if (tc.isInstance(t)) return tc.cast(t); if (t instanceof Error) throw (Error) t; if (t instanceof RuntimeException) throw (RuntimeException) t; throw InternalError("undeclared checked exception", t); } This guy should be in the JDK, in case the set of unchecked throwables grows (e.g., to include non-local jump types). -- John P.S. Here's a good Java puzzler: Without using any non-standard language features, figure out how to generalize checkedException to two or more variable throws types. On May 2, 2009, at 6:00 PM, Paul Benedict wrote: >>> Sorry, wrapping checked exceptions is a non-starter for 292. >>> Wrapping >>> of all sorts is one of the reasons reflection is unusably slow for >>> dynamic language implementation. > > Good point. But I think it is a bad idea to alter the JLS to catch > undeclared checked exceptions -- if that is really being considered. > > Neal appears to be correct in requiring that a dynamic call site > throws Throwable. Dynamic languages can ingnore the exceptions if they > want, but the Java code shouldn't. > > -- Paul > From pbenedict at apache.org Sat Jun 13 21:51:45 2009 From: pbenedict at apache.org (Paul Benedict) Date: Sat, 13 Jun 2009 23:51:45 -0500 Subject: Points about language support for 292 Message-ID: John, >>Although I doubted at first, I now agree (with Alex, Neal, et al) that >>where JSR 292 punches into the JLS, it should not bring a new loophole >>in the static checking of throws and catches. When a language feature "punches into the JLS", isn't it mandatory those features exist in the java.lang namespace? Perhaps this was discussed before (and I missed it), but I hope "java.dyn" migrates into "java.lang.dyn" due to its effect on the JLS. Paul From gavin.king at gmail.com Wed Jun 17 15:03:00 2009 From: gavin.king at gmail.com (Gavin King) Date: Wed, 17 Jun 2009 15:03:00 -0700 Subject: Expressions for annotation values and parameterized types. Message-ID: Hi folks, something that has come up in JSR-299 is the fact that Java provides no easy expression syntax for: * annotation values * parameterized types We have to jump through hoops instead of being able to write: Named named = @Named( getName() ); or: ParameterizedType> type = Set.class; These problems certainly have (ugly) workarounds, and that's why 299 introduces AnnotationLiteral and TypeLiteral, but it would be great if these helper classes could be hidden by the compiler. These issues are becoming more important as Java APIs move in the direction of greater typesafety. I'm happy to work on a more formal proposal if there is interest in addressing these issues. -- Gavin King gavin.king at gmail.com http://in.relation.to/Bloggers/Gavin http://hibernate.org http://seamframework.org From Joe.Darcy at Sun.COM Wed Jun 17 15:39:11 2009 From: Joe.Darcy at Sun.COM (Joe Darcy) Date: Wed, 17 Jun 2009 15:39:11 -0700 Subject: Expressions for annotation values and parameterized types. In-Reply-To: References: Message-ID: <4A39708F.2070104@sun.com> Hello. Gavin King wrote: > Hi folks, > > something that has come up in JSR-299 is the fact that Java provides > no easy expression syntax for: > > * annotation values > * parameterized types > > We have to jump through hoops instead of being able to write: > > Named named = @Named( getName() ); > > or: > > ParameterizedType> type = Set.class; > > These problems certainly have (ugly) workarounds, and that's why 299 > introduces AnnotationLiteral and TypeLiteral, but it would be great if > these helper classes could be hidden by the compiler. > > These issues are becoming more important as Java APIs move in the > direction of greater typesafety. > > I'm happy to work on a more formal proposal if there is interest in > addressing these issues. The window to submit small language change proposals for JDK 7 expired several months ago and we won't be accepting any more now. However, it is still possible for library changes to be made in JDK 7 so if some form of the improvements can be expressed as libraries, they might still get in. -Joe From Joe.Darcy at Sun.COM Mon Jun 22 12:19:48 2009 From: Joe.Darcy at Sun.COM (Joseph D. Darcy) Date: Mon, 22 Jun 2009 12:19:48 -0700 Subject: Indexing access for Lists and Maps considered harmful? Message-ID: <4A3FD954.6020709@sun.com> Hello. A recent blog post cited in Alex Miller's handy "Java 7 Links" (http://java7.tumblr.com) claims that adding indexing support for Lists and Maps would be harmful because of an arguably surprising behavior on compound assignment. After map["a"] = map["b"] = "c"; the new value for key "a" would be the old mapping of "b" and not necessarily "c" because a call to the put method returns the old value. I'm not too concerned about this interaction because compound assignment is relatively infrequent; however, I think a lint warning from the compiler would be appropriate in this case. Also, an IDE could color the non-array uses of "[]" differently to highlight any potential differences in semantics. As a meta-comment, I find it odd that if someone wanted to inform the coin discussion he or she would not directly email the coin list in addition to or instead of posting a blog entry. -Joe From tim at peierls.net Mon Jun 22 12:33:33 2009 From: tim at peierls.net (Tim Peierls) Date: Mon, 22 Jun 2009 15:33:33 -0400 Subject: Indexing access for Lists and Maps considered harmful? In-Reply-To: <4A3FD954.6020709@sun.com> References: <4A3FD954.6020709@sun.com> Message-ID: <63b4e4050906221233n1c1640c5tceff160a72140319@mail.gmail.com> Cool way to do swap and cyclic shift without temporaries: m[a] = m[b] = m[c] = m[a]; I love it! Can I have it, can I, huh? :-) Seriously, I don't think this is a showstopper. --tim On Mon, Jun 22, 2009 at 3:19 PM, Joseph D. Darcy wrote: > Hello. > > A recent blog post cited in Alex Miller's handy "Java 7 Links" > (http://java7.tumblr.com) claims that adding indexing support for Lists > and Maps would be harmful because of an arguably surprising behavior on > compound assignment. After > > map["a"] = map["b"] = "c"; > > the new value for key "a" would be the old mapping of "b" and not > necessarily "c" because a call to the put method returns the old value. > > I'm not too concerned about this interaction because compound assignment > is relatively infrequent; however, I think a lint warning from the > compiler would be appropriate in this case. Also, an IDE could color > the non-array uses of "[]" differently to highlight any potential > differences in semantics. > > As a meta-comment, I find it odd that if someone wanted to inform the > coin discussion he or she would not directly email the coin list in > addition to or instead of posting a blog entry. > > -Joe > > From Thomas.Hawtin at Sun.COM Mon Jun 22 12:35:35 2009 From: Thomas.Hawtin at Sun.COM (Tom Hawtin) Date: Mon, 22 Jun 2009 20:35:35 +0100 Subject: Indexing access for Lists and Maps considered harmful? In-Reply-To: <4A3FD954.6020709@sun.com> References: <4A3FD954.6020709@sun.com> Message-ID: <4A3FDD07.4010509@sun.com> Joseph D. Darcy wrote: > map["a"] = map["b"] = "c"; > > the new value for key "a" would be the old mapping of "b" and not > necessarily "c" because a call to the put method returns the old value. > > I'm not too concerned about this interaction because compound assignment > is relatively infrequent; however, I think a lint warning from the > compiler would be appropriate in this case. [...] My interpretation of Java's feel is that there should be no warnings. If something is really dodgy it shouldn't compile. I understand, warnings were added later as a kludge. As this is a new feature, there is no need for it to be a warning. The construct should be outlawed, probably by making this new feature effectively return void. Tom Hawtin From neal at gafter.com Mon Jun 22 12:42:56 2009 From: neal at gafter.com (Neal Gafter) Date: Mon, 22 Jun 2009 12:42:56 -0700 Subject: Indexing access for Lists and Maps considered harmful? In-Reply-To: <4A3FD954.6020709@sun.com> References: <4A3FD954.6020709@sun.com> Message-ID: <15e8b9d20906221242h764bd65fi1989ea8852c827c1@mail.gmail.com> I don't think the indexing operator has to be defined in a way that isn't parallel to the way indexing works with ordinary arrays. I would expect the result of the expression map["b"] = "c" to be the value "c". We can have that if the construct is defined by translation as: var tmp = "c"; map.put("b", tmp); tmp What is the point, you might ask, of the interface definition of "put" returning a value that the language always ignores? My answer is that this is an error in the specification; a language construct such as the indexing operators that can be defined by a syntactic translation can ignore the types. That simplifies the specification and the implementation, and it allows the operator to be more widely retrofitted. The same comment applies to the ARM proposal: a pattern based approach would make it more widely applicable and retrofittable, especially with extension methods. This is one of the most important (but usually ignored) benefits of extension methods. Regards, Neal On Mon, Jun 22, 2009 at 12:19 PM, Joseph D. Darcy wrote: > Hello. > > A recent blog post cited in Alex Miller's handy "Java 7 Links" > (http://java7.tumblr.com) claims that adding indexing support for Lists > and Maps would be harmful because of an arguably surprising behavior on > compound assignment. After > > map["a"] = map["b"] = "c"; > > the new value for key "a" would be the old mapping of "b" and not > necessarily "c" because a call to the put method returns the old value. > > I'm not too concerned about this interaction because compound assignment > is relatively infrequent; however, I think a lint warning from the > compiler would be appropriate in this case. Also, an IDE could color > the non-array uses of "[]" differently to highlight any potential > differences in semantics. > > As a meta-comment, I find it odd that if someone wanted to inform the > coin discussion he or she would not directly email the coin list in > addition to or instead of posting a blog entry. > > -Joe > > From rssh at gradsoft.com.ua Mon Jun 22 08:28:38 2009 From: rssh at gradsoft.com.ua (Ruslan Shevchenko) Date: Mon, 22 Jun 2009 18:28:38 +0300 (EEST) Subject: Indexing access for Lists and Maps considered harmful? In-Reply-To: <4A3FD954.6020709@sun.com> References: <4A3FD954.6020709@sun.com> Message-ID: <5919185d787be17ab446163e0e03ffb2.squirrel@wmail.gradsoft.ua> > Hello. > > A recent blog post cited in Alex Miller's handy "Java 7 Links" > (http://java7.tumblr.com) claims that adding indexing support for Lists > and Maps would be harmful because of an arguably surprising behavior on > compound assignment. After > > map["a"] = map["b"] = "c"; > > the new value for key "a" would be the old mapping of "b" and not > necessarily "c" because a call to the put method returns the old value. > > I'm not too concerned about this interaction because compound assignment > is relatively infrequent; however, I think a lint warning from the > compiler would be appropriate in this case. Also, an IDE could color > the non-array uses of "[]" differently to highlight any potential > differences in semantics. > Hmm, are semantics of "[]" must be exactly equal to semantics of put ? (if I remember, [] proposal come to us without JLS part) i. e. it is possible introduce another pair of methods instead put/get, or just ignore return value of put, i. e. map["b"]="c" will be translated to pseudocode {map.put("b","c"), c} > As a meta-comment, I find it odd that if someone wanted to inform the > coin discussion he or she would not directly email the coin list in > addition to or instead of posting a blog entry. > > -Joe > > From lk at teamten.com Mon Jun 22 13:40:16 2009 From: lk at teamten.com (Lawrence Kesteloot) Date: Mon, 22 Jun 2009 13:40:16 -0700 Subject: Indexing access for Lists and Maps considered harmful? In-Reply-To: <4A3FD954.6020709@sun.com> References: <4A3FD954.6020709@sun.com> Message-ID: <997cab100906221340s340aec87p6197ddff8ef9669d@mail.gmail.com> On Mon, Jun 22, 2009 at 12:19 PM, Joseph D. Darcy wrote: > map["a"] = map["b"] = "c"; > > the new value for key "a" would be the old mapping of "b" and not > necessarily "c" because a call to the put method returns the old value. There is no way that: map["b"] = "c" can return anything other than "c". Returning the old value or returning void would violate 40 years of C-based expectations (including the identical construct in the STL). It must either return "c" or not be implemented at all. Lawrence From reinier at zwitserloot.com Mon Jun 22 14:51:00 2009 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Mon, 22 Jun 2009 23:51:00 +0200 Subject: Indexing access for Lists and Maps considered harmful? In-Reply-To: <997cab100906221340s340aec87p6197ddff8ef9669d@mail.gmail.com> References: <4A3FD954.6020709@sun.com> <997cab100906221340s340aec87p6197ddff8ef9669d@mail.gmail.com> Message-ID: <7D0E102C-44DA-4263-82F1-B94BE99C1260@zwitserloot.com> I agree that the expression "map[c] = d" returning the OLD value of map[c] (e.g. usually null) is unacceptable behaviour, but I think this propsoal would fare just fine if this form of operation is defined to return void and not 'd', in order to avoid confusion. There are many code bases that never use pass-through assignment, and the workaround (write it out...) is by definition not more boilerplate and noise than what we have now. I do lean slightly to preferring the expression to return 'd', and not void, nor 'old mapping of c'. --Reinier Zwitserloot On 2009/22/06, at 22:40, Lawrence Kesteloot wrote: > On Mon, Jun 22, 2009 at 12:19 PM, Joseph D. Darcy > wrote: >> map["a"] = map["b"] = "c"; >> >> the new value for key "a" would be the old mapping of "b" and not >> necessarily "c" because a call to the put method returns the old >> value. > > There is no way that: > > map["b"] = "c" > > can return anything other than "c". Returning the old value or > returning void would violate 40 years of C-based expectations > (including the identical construct in the STL). It must either return > "c" or not be implemented at all. > > Lawrence > From talden at gmail.com Mon Jun 22 18:25:20 2009 From: talden at gmail.com (Talden) Date: Tue, 23 Jun 2009 13:25:20 +1200 Subject: Indexing access for Lists and Maps considered harmful? In-Reply-To: <15e8b9d20906221242h764bd65fi1989ea8852c827c1@mail.gmail.com> References: <4A3FD954.6020709@sun.com> <15e8b9d20906221242h764bd65fi1989ea8852c827c1@mail.gmail.com> Message-ID: <738d207f0906221825n4ca69861he53200f41c7aec73@mail.gmail.com> > ... ?We can have that if the construct is defined by > translation as: > > var tmp = "c"; > map.put("b", tmp); > tmp This is my preference too... m[a] = n[a] = x; // where m and n are maps. becomes X t = x; m.put(a, t); n.put(a, t); t; Does semantically treating all multi-assignments this way break existing code? a = b = c; C t = c; a = t; b = t; t; Are there ways to get other side-effects in the current grammar? If not, defining it this way makes defining it for indexed access easier. PS: I've thought about this just long enough to write this email, it's one of those days... I must have missed something that makes this a more complex discussion other than 'this is how we should define the value of an indexed access expression'. -- Talden From Joe.Darcy at Sun.COM Mon Jun 22 22:46:25 2009 From: Joe.Darcy at Sun.COM (Joseph D. Darcy) Date: Mon, 22 Jun 2009 22:46:25 -0700 Subject: Indexing access for Lists and Maps considered harmful? In-Reply-To: <7D0E102C-44DA-4263-82F1-B94BE99C1260@zwitserloot.com> References: <4A3FD954.6020709@sun.com> <997cab100906221340s340aec87p6197ddff8ef9669d@mail.gmail.com> <7D0E102C-44DA-4263-82F1-B94BE99C1260@zwitserloot.com> Message-ID: <4A406C31.9060305@sun.com> My current preference is to keep a simple desugaring of the indexing operators into method calls. While collection usage would certainly be a common case, there are probably other to-be-written APIs that would benefit from the translation into method calls. -Joe Reinier Zwitserloot wrote: > I agree that the expression "map[c] = d" returning the OLD value of > map[c] (e.g. usually null) is unacceptable behaviour, but I think this > propsoal would fare just fine if this form of operation is defined to > return void and not 'd', in order to avoid confusion. There are many > code bases that never use pass-through assignment, and the workaround > (write it out...) is by definition not more boilerplate and noise than > what we have now. > > > I do lean slightly to preferring the expression to return 'd', and not > void, nor 'old mapping of c'. > > --Reinier Zwitserloot > > > > On 2009/22/06, at 22:40, Lawrence Kesteloot wrote: > > >> On Mon, Jun 22, 2009 at 12:19 PM, Joseph D. Darcy >> wrote: >> >>> map["a"] = map["b"] = "c"; >>> >>> the new value for key "a" would be the old mapping of "b" and not >>> necessarily "c" because a call to the put method returns the old >>> value. >>> >> There is no way that: >> >> map["b"] = "c" >> >> can return anything other than "c". Returning the old value or >> returning void would violate 40 years of C-based expectations >> (including the identical construct in the STL). It must either return >> "c" or not be implemented at all. >> >> Lawrence >> >> > > > From reinier at zwitserloot.com Mon Jun 22 23:18:47 2009 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Tue, 23 Jun 2009 08:18:47 +0200 Subject: Indexing access for Lists and Maps considered harmful? In-Reply-To: <4A406C31.9060305@sun.com> References: <4A3FD954.6020709@sun.com> <997cab100906221340s340aec87p6197ddff8ef9669d@mail.gmail.com> <7D0E102C-44DA-4263-82F1-B94BE99C1260@zwitserloot.com> <4A406C31.9060305@sun.com> Message-ID: <647E7BD7-3329-4054-83D1-ED162863A28D@zwitserloot.com> You realize this is going to be an instant java puzzler, right? I thought one of the soft goals of project coin is to attempt to sidestep obvious puzzlers. I also admit that I cannot come up with any situation where the expression: thingA[thingB] = thingC; evaluating to something that ISNT 'thingC' (or void) is going to be the logical, not confusing choice. Suggestion: Define this operation to return void regardless of the underlying method implementation's actual return value. That way, if in the future a solid use case for letting the method invocation decide return type and value is found, a change can be made without breaking old code. If, on the other hand, there's a clamour for letting this expression return 'thingC', that can be added to a future version of java as well. In other words, picking EITHER "That evaluates to thingC" OR "That evaluates to whatever the put method returns" is a choice you must make for the rest of the life of the java language. On the other hand, picking "That is a statement and not an expression (e.g. evaluates to void)" is not a life-long choice; if it ends up being a bad choice, you can switch to either alternative later without any pain other than filing a purely additive language change. The only obvious disadvantage to 'return void' that I can see is that its inconsistent with both the current behaviour of the assignment operator AND the desugaring idea, whereas the alternatives are consistent with one behaviour and inconsistent with the other. Then again, with 'returns thingC' and 'returns returntype of put method', the inconsistent behaviour is silent, puzzler-esque, and going to cause hundreds of people subtle and hard to find bugs, whereas in the 'returns void' scenario, there is no confusion at all, as the compiler/ editor will instantly tell you that the assignment is a statement and not an expression. I just talked myself into throwing my overwhelming support behind the return void choice. Both other choices lead to long bug hunts and confusion that can only be solved by experimenting or grabbing the JLS, whereas void can't lead to bug hunts and any confusion it engenders is instantly assuaged by a compiler hint. --Reinier Zwitserloot On 2009/23/06, at 07:46, Joseph D. Darcy wrote: > My current preference is to keep a simple desugaring of the indexing > operators into method calls. While collection usage would certainly > be a common case, there are probably other to-be-written APIs that > would benefit from the translation into method calls. > > -Joe > > Reinier Zwitserloot wrote: >> I agree that the expression "map[c] = d" returning the OLD value >> of map[c] (e.g. usually null) is unacceptable behaviour, but I >> think this propsoal would fare just fine if this form of operation >> is defined to return void and not 'd', in order to avoid >> confusion. There are many code bases that never use pass-through >> assignment, and the workaround (write it out...) is by definition >> not more boilerplate and noise than what we have now. >> >> >> I do lean slightly to preferring the expression to return 'd', and >> not void, nor 'old mapping of c'. >> >> --Reinier Zwitserloot >> >> >> >> On 2009/22/06, at 22:40, Lawrence Kesteloot wrote: >> >> >>> On Mon, Jun 22, 2009 at 12:19 PM, Joseph D. >>> Darcy wrote: >>> >>>> map["a"] = map["b"] = "c"; >>>> >>>> the new value for key "a" would be the old mapping of "b" and not >>>> necessarily "c" because a call to the put method returns the old >>>> value. >>>> >>> There is no way that: >>> >>> map["b"] = "c" >>> >>> can return anything other than "c". Returning the old value or >>> returning void would violate 40 years of C-based expectations >>> (including the identical construct in the STL). It must either >>> return >>> "c" or not be implemented at all. >>> >>> Lawrence >>> >>> >> >> >> > From ted at tedneward.com Tue Jun 23 01:09:39 2009 From: ted at tedneward.com (Ted Neward) Date: Tue, 23 Jun 2009 01:09:39 -0700 Subject: Indexing access for Lists and Maps considered harmful? In-Reply-To: <647E7BD7-3329-4054-83D1-ED162863A28D@zwitserloot.com> References: <4A3FD954.6020709@sun.com> <997cab100906221340s340aec87p6197ddff8ef9669d@mail.gmail.com> <7D0E102C-44DA-4263-82F1-B94BE99C1260@zwitserloot.com> <4A406C31.9060305@sun.com> <647E7BD7-3329-4054-83D1-ED162863A28D@zwitserloot.com> Message-ID: <04a501c9f3da$0869c7a0$193d56e0$@com> Except that the semantics of "=" (assignment) are chained, such that a = b = c; should evaluate to "c", with "a" and "b" now holding the value that "c" started off with; in other words, map[a] = map[b] = c; means that map[b] should return c, and so should map[a]. As much as returning void is the 'safe' choice, consistency with assignment in other contexts and expression evaluation order argues that it should return the value of whatever was just put there (c). Ted Neward | Principal Consultant, ThoughtWorks Java, .NET, XML Services Consulting, Teaching, Speaking, Writing http://www.thoughtworks.com | http://www.tedneward.com > -----Original Message----- > From: coin-dev-bounces at openjdk.java.net [mailto:coin-dev- > bounces at openjdk.java.net] On Behalf Of Reinier Zwitserloot > Sent: Monday, June 22, 2009 11:19 PM > To: Joseph D. Darcy > Cc: coin-dev at openjdk.java.net > Subject: Re: Indexing access for Lists and Maps considered harmful? > > You realize this is going to be an instant java puzzler, right? I > thought one of the soft goals of project coin is to attempt to > sidestep obvious puzzlers. > > I also admit that I cannot come up with any situation where the > expression: > > thingA[thingB] = thingC; > > evaluating to something that ISNT 'thingC' (or void) is going to be > the logical, not confusing choice. > > > Suggestion: Define this operation to return void regardless of the > underlying method implementation's actual return value. That way, if > in the future a solid use case for letting the method invocation > decide return type and value is found, a change can be made without > breaking old code. If, on the other hand, there's a clamour for > letting this expression return 'thingC', that can be added to a future > version of java as well. > > In other words, picking EITHER "That evaluates to thingC" OR "That > evaluates to whatever the put method returns" is a choice you must > make for the rest of the life of the java language. On the other hand, > picking "That is a statement and not an expression (e.g. evaluates to > void)" is not a life-long choice; if it ends up being a bad choice, > you can switch to either alternative later without any pain other than > filing a purely additive language change. > > > The only obvious disadvantage to 'return void' that I can see is that > its inconsistent with both the current behaviour of the assignment > operator AND the desugaring idea, whereas the alternatives are > consistent with one behaviour and inconsistent with the other. Then > again, with 'returns thingC' and 'returns returntype of put method', > the inconsistent behaviour is silent, puzzler-esque, and going to > cause hundreds of people subtle and hard to find bugs, whereas in the > 'returns void' scenario, there is no confusion at all, as the compiler/ > editor will instantly tell you that the assignment is a statement and > not an expression. > > > I just talked myself into throwing my overwhelming support behind the > return void choice. Both other choices lead to long bug hunts and > confusion that can only be solved by experimenting or grabbing the > JLS, whereas void can't lead to bug hunts and any confusion it > engenders is instantly assuaged by a compiler hint. > > --Reinier Zwitserloot > > > > On 2009/23/06, at 07:46, Joseph D. Darcy wrote: > > > My current preference is to keep a simple desugaring of the indexing > > operators into method calls. While collection usage would certainly > > be a common case, there are probably other to-be-written APIs that > > would benefit from the translation into method calls. > > > > -Joe > > > > Reinier Zwitserloot wrote: > >> I agree that the expression "map[c] = d" returning the OLD value > >> of map[c] (e.g. usually null) is unacceptable behaviour, but I > >> think this propsoal would fare just fine if this form of operation > >> is defined to return void and not 'd', in order to avoid > >> confusion. There are many code bases that never use pass-through > >> assignment, and the workaround (write it out...) is by definition > >> not more boilerplate and noise than what we have now. > >> > >> > >> I do lean slightly to preferring the expression to return 'd', and > >> not void, nor 'old mapping of c'. > >> > >> --Reinier Zwitserloot > >> > >> > >> > >> On 2009/22/06, at 22:40, Lawrence Kesteloot wrote: > >> > >> > >>> On Mon, Jun 22, 2009 at 12:19 PM, Joseph D. > >>> Darcy wrote: > >>> > >>>> map["a"] = map["b"] = "c"; > >>>> > >>>> the new value for key "a" would be the old mapping of "b" and not > >>>> necessarily "c" because a call to the put method returns the old > >>>> value. > >>>> > >>> There is no way that: > >>> > >>> map["b"] = "c" > >>> > >>> can return anything other than "c". Returning the old value or > >>> returning void would violate 40 years of C-based expectations > >>> (including the identical construct in the STL). It must either > >>> return > >>> "c" or not be implemented at all. > >>> > >>> Lawrence > >>> > >>> > >> > >> > >> > > From abies at adres.pl Tue Jun 23 02:21:11 2009 From: abies at adres.pl (abies at adres.pl) Date: Tue, 23 Jun 2009 11:21:11 +0200 Subject: Indexing access for Lists and Maps considered harmful? In-Reply-To: 647E7BD7-3329-4054-83D1-ED162863A28D@zwitserloot.com Message-ID: Hello, If we have following statement String x = coll[0] = "ABC"; it should work in the same way if coll is a) native String[] array b) java.util.List c) java.util.Map I think that it would be very suprising to have different behaviour depending on the type of collection. This means it is not possible to get old value from the map on replace, while using [] operator - but same way as foreach on arrays is missing index, I think it is good tradeoff for having common usage consistent with rest of the language. In the few cases you need return value, you can use normal method call. With best regards, Artur Biesiadowski From brucechapman at paradise.net.nz Tue Jun 23 03:03:30 2009 From: brucechapman at paradise.net.nz (Bruce Chapman) Date: Tue, 23 Jun 2009 22:03:30 +1200 Subject: Indexing access for Lists and Maps considered harmful? In-Reply-To: <738d207f0906221825n4ca69861he53200f41c7aec73@mail.gmail.com> References: <4A3FD954.6020709@sun.com> <15e8b9d20906221242h764bd65fi1989ea8852c827c1@mail.gmail.com> <738d207f0906221825n4ca69861he53200f41c7aec73@mail.gmail.com> Message-ID: <4A40A872.7050202@paradise.net.nz> Talden wrote: >> ... We can have that if the construct is defined by >> translation as: >> >> var tmp = "c"; >> map.put("b", tmp); >> tmp >> > > This is my preference too... > > m[a] = n[a] = x; // where m and n are maps. > > becomes > > X t = x; > m.put(a, t); n.put(a, t); > t; > Not quite! because assignment is right associative - therfore m[a] = n[a] = x; happens in the same order as m[a] = (n[a] = x); and therefore your translation should be becomes X t = x; n.put(a, t); m.put(a, t); t; The difference could be detected for example when n and m were both references to the same LinkedHashMap and the keys were different therefore the order of iteration would reflect the order of assignment. Bruce > Does semantically treating all multi-assignments this way break existing code? > > a = b = c; > > C t = c; > a = t; b = t; > t; > > Are there ways to get other side-effects in the current grammar? If > not, defining it this way makes defining it for indexed access easier. > > PS: I've thought about this just long enough to write this email, it's > one of those days... I must have missed something that makes this a > more complex discussion other than 'this is how we should define the > value of an indexed access expression'. > > -- > Talden > > From ARDOINT at fr.ibm.com Tue Jun 23 05:09:27 2009 From: ARDOINT at fr.ibm.com (Jean Louis Ardoint) Date: Tue, 23 Jun 2009 14:09:27 +0200 Subject: Indexing access for Lists and Maps considered harmful? In-Reply-To: <4A40A872.7050202@paradise.net.nz> References: <4A3FD954.6020709@sun.com> <15e8b9d20906221242h764bd65fi1989ea8852c827c1@mail.gmail.com> <738d207f0906221825n4ca69861he53200f41c7aec73@mail.gmail.com> <4A40A872.7050202@paradise.net.nz> Message-ID: You can also easily encounter this with prefix or postfix operators and autoboxing, like in: Map m; ... m[i] = m[i++]++ = i++; Jean-Louis From: Bruce Chapman To: coin-dev Date: 23/06/2009 12:04 Subject: Re: Indexing access for Lists and Maps considered harmful? Sent by: coin-dev-bounces at openjdk.java.net Talden wrote: >> ... We can have that if the construct is defined by >> translation as: >> >> var tmp = "c"; >> map.put("b", tmp); >> tmp >> > > This is my preference too... > > m[a] = n[a] = x; // where m and n are maps. > > becomes > > X t = x; > m.put(a, t); n.put(a, t); > t; > Not quite! because assignment is right associative - therfore m[a] = n[a] = x; happens in the same order as m[a] = (n[a] = x); and therefore your translation should be becomes X t = x; n.put(a, t); m.put(a, t); t; The difference could be detected for example when n and m were both references to the same LinkedHashMap and the keys were different therefore the order of iteration would reflect the order of assignment. Bruce > Does semantically treating all multi-assignments this way break existing code? > > a = b = c; > > C t = c; > a = t; b = t; > t; > > Are there ways to get other side-effects in the current grammar? If > not, defining it this way makes defining it for indexed access easier. > > PS: I've thought about this just long enough to write this email, it's > one of those days... I must have missed something that makes this a > more complex discussion other than 'this is how we should define the > value of an indexed access expression'. > > -- > Talden > > Sauf indication contraire ci-dessus:/ Unless stated otherwise above: Compagnie IBM France Si?ge Social : Tour Descartes, 2, avenue Gambetta, La D?fense 5, 92400 Courbevoie RCS Nanterre 552 118 465 Forme Sociale : S.A.S. Capital Social : 609.751.783,30 ? SIREN/SIRET : 552 118 465 02430 From Thomas.Hawtin at Sun.COM Tue Jun 23 06:43:28 2009 From: Thomas.Hawtin at Sun.COM (Tom Hawtin) Date: Tue, 23 Jun 2009 14:43:28 +0100 Subject: Indexing access for Lists and Maps considered harmful? In-Reply-To: <4A40A872.7050202@paradise.net.nz> References: <4A3FD954.6020709@sun.com> <15e8b9d20906221242h764bd65fi1989ea8852c827c1@mail.gmail.com> <738d207f0906221825n4ca69861he53200f41c7aec73@mail.gmail.com> <4A40A872.7050202@paradise.net.nz> Message-ID: <4A40DC00.50808@sun.com> Bruce Chapman wrote: > > m[a] = (n[a] = x); > > and therefore your translation should be > > becomes > > X t = x; > n.put(a, t); > m.put(a, t); > t; It's more subtle than that in the presence of side effects. Consider: int[] a = new int[2009]; int i = 1; a[i++] = a[0] = i; System.err.println(a[1]); That prints 2, because the post increment is on the left, while evaluation is more or less left to right (my JLS is in the other office). Then there is boxing and conversions between primitive types, which just makes the whole thing positively evil. Tom From spamolovko at gmail.com Tue Jun 23 06:59:26 2009 From: spamolovko at gmail.com (spamolovko) Date: Tue, 23 Jun 2009 17:59:26 +0400 Subject: Indexing access for Lists and Maps considered harmful? Message-ID: <4A40DFBE.6030204@gmail.com> Better way for m[a] = n[a] = x; is to become this byte-code n.put(a, x); m.put(a, n.get(a)); this is because m[a] = n[a]; must be translate into: m.put(a, n.get(a)); So i do not see any problems with side-effect grammar like String x = coll[0] = "ABC"; because it become: coll.put(0, "ABC"); String x = coll.get(0); PS i remember that coin project had discussion about usage of special interface for "indexing access". That interface have to use it's own methods for access to data, so no problems with get semantic. Example: public interface Indexer { public ValueType indexGet(KeyType key); public void indexSet(KeyType key, ValueType value); } import java.util.HashMap; public class MyCoolMap extends HashMap implements Indexer { public ValueType indexGet(KeyType key) { return get(key); } public void indexSet(KeyType key, ValueType value) { put(key, value); } } public class Usage { static public void main(String[] args) { MyCoolMap map = new MyCoolMap(); // map["A"] = map["B"] = "hello"; map.indexSet("B", "hello"); map.indexSet("A", map.indexGet("B")); } } BR. From Joe.Darcy at Sun.COM Tue Jun 23 10:36:09 2009 From: Joe.Darcy at Sun.COM (Joseph D. Darcy) Date: Tue, 23 Jun 2009 10:36:09 -0700 Subject: Indexing access for Lists and Maps considered harmful? In-Reply-To: <4A40DFBE.6030204@gmail.com> References: <4A40DFBE.6030204@gmail.com> Message-ID: <4A411289.30808@sun.com> spamolovko wrote: [snip] > > PS i remember that coin project had discussion about usage of special > interface for "indexing access". That interface have to use it's own > methods for access to data, so no problems with get semantic. > > Example: > > public interface Indexer { > > public ValueType indexGet(KeyType key); > > public void indexSet(KeyType key, ValueType value); > > } > [snip] The idea would be to retrofit new superinterfaces onto the List and Map interfaces without adding new methods to the interfaces. For example, here is a slight refinement of strawman interfaces of that sort from my JavaOne talk: // New superinterfaces to indicate syntax? interface GettableFromInt { E get(int); } interface Gettable { V get(K k); } interface Settable { E set(int, E e); } interface Puttable { V put(K k, V v); } java.util.List extends GettableFromInt, Settable, ? java.util.Map extends Gettable, Puttable(K, V), ? The names "Gettable" etc. are open to improvement :-) -Joe From neal at gafter.com Tue Jun 23 10:52:29 2009 From: neal at gafter.com (Neal Gafter) Date: Tue, 23 Jun 2009 10:52:29 -0700 Subject: Indexing access for Lists and Maps considered harmful? In-Reply-To: <4A411289.30808@sun.com> References: <4A40DFBE.6030204@gmail.com> <4A411289.30808@sun.com> Message-ID: <15e8b9d20906231052j7d55c943m4bbe81284a854b1a@mail.gmail.com> Why would a language-support method like Puttable.put return a value that the generated code is required to ignore? From the point of view of designing a language-support API, it makes no sense whatsoever. The return type is vestigal: it is only present because of the way that we are considering retrofitting it onto some existing APIs, but it forces any new APIs that are retrofitted to return some (arbitrary) value to be ignored. It also imposes a performance penalty on implementations that can more efficiently overwrite a mapping than overwrite AND return the old value. This is a language-design smell that suggests we should consider finding another strategy for getting the effect of index operators. On Tue, Jun 23, 2009 at 10:36 AM, Joseph D. Darcy wrote: > spamolovko wrote: > > [snip] > > > > PS i remember that coin project had discussion about usage of special > > interface for "indexing access". That interface have to use it's own > > methods for access to data, so no problems with get semantic. > > > > Example: > > > > public interface Indexer { > > > > public ValueType indexGet(KeyType key); > > > > public void indexSet(KeyType key, ValueType value); > > > > } > > > > [snip] > > The idea would be to retrofit new superinterfaces onto the List and Map > interfaces without adding new methods to the interfaces. For example, > here is a slight refinement of strawman interfaces of that sort from my > JavaOne talk: > > // New superinterfaces to indicate syntax? > interface GettableFromInt { > E get(int); > } > > interface Gettable { > V get(K k); > } > > interface Settable { > E set(int, E e); > } > interface Puttable { > V put(K k, V v); > } > > java.util.List extends GettableFromInt, Settable, ? > > java.util.Map extends Gettable, Puttable(K, V), ? > > The names "Gettable" etc. are open to improvement :-) > > -Joe > > From abies at adres.pl Tue Jun 23 11:02:37 2009 From: abies at adres.pl (Artur Biesiadowski) Date: Tue, 23 Jun 2009 20:02:37 +0200 Subject: Indexing access for Lists and Maps considered harmful? In-Reply-To: <4A411289.30808@sun.com> References: <4A40DFBE.6030204@gmail.com> <4A411289.30808@sun.com> Message-ID: <4A4118BD.8090802@adres.pl> Joseph D. Darcy wrote: > // New superinterfaces to indicate syntax? > interface GettableFromInt { > E get(int); > } > > interface Gettable { > V get(K k); > } > > interface Settable { > E set(int, E e); > } > interface Puttable { > V put(K k, V v); > } > If anything like that is implemented, I would rather see it as two interfaces - ListAccess and MapAccess (or maybe IndexAccess and Key/DictionaryAccess to be less collection-oriented?). Read-only or write-only classes can throw runtime exceptions if needed. Do you think that one-operation classes would be common? I can see a possible benefit of detecting this at compile time instead of runtime, but how useful it would be in real world... All collection classes would be read-write (even for immutable collections no way to indicate it on interface level). String could be probably made 'GettableFromInt'. StringBuilder/Buffer is already read-write. Same goes for BitSet. I think it boils down to question if we want to have String txt = "ABC"; txt[0] = 'X'; failing at compile time or runtime. On the other hand, in case of String, I could imagine most IDEs making it a warning at compile time easily... Regards, Artur Biesiadowski From Joe.Darcy at Sun.COM Tue Jun 23 11:06:20 2009 From: Joe.Darcy at Sun.COM (Joseph D. Darcy) Date: Tue, 23 Jun 2009 11:06:20 -0700 Subject: Indexing access for Lists and Maps considered harmful? In-Reply-To: <647E7BD7-3329-4054-83D1-ED162863A28D@zwitserloot.com> References: <4A3FD954.6020709@sun.com> <997cab100906221340s340aec87p6197ddff8ef9669d@mail.gmail.com> <7D0E102C-44DA-4263-82F1-B94BE99C1260@zwitserloot.com> <4A406C31.9060305@sun.com> <647E7BD7-3329-4054-83D1-ED162863A28D@zwitserloot.com> Message-ID: <4A41199C.9070209@sun.com> Reinier Zwitserloot wrote: > You realize this is going to be an instant java puzzler, right? I > thought one of the soft goals of project coin is to attempt to > sidestep obvious puzzlers. It may be the case that changing the desugaring to return void in these cases is the right thing to do in the end. However, the mere existence of *some* puzzler should not be sufficient to derail a coin proposal. I fully expect the language changes to enable new, initially unexpected program behavior; that does have to be more than compensated by the new, expected programs behavior that is allowed of course :-) -Joe > > I also admit that I cannot come up with any situation where the > expression: > > thingA[thingB] = thingC; > > evaluating to something that ISNT 'thingC' (or void) is going to be > the logical, not confusing choice. > > > Suggestion: Define this operation to return void regardless of the > underlying method implementation's actual return value. That way, if > in the future a solid use case for letting the method invocation > decide return type and value is found, a change can be made without > breaking old code. If, on the other hand, there's a clamour for > letting this expression return 'thingC', that can be added to a future > version of java as well. > > In other words, picking EITHER "That evaluates to thingC" OR "That > evaluates to whatever the put method returns" is a choice you must > make for the rest of the life of the java language. On the other hand, > picking "That is a statement and not an expression (e.g. evaluates to > void)" is not a life-long choice; if it ends up being a bad choice, > you can switch to either alternative later without any pain other than > filing a purely additive language change. > > > The only obvious disadvantage to 'return void' that I can see is that > its inconsistent with both the current behaviour of the assignment > operator AND the desugaring idea, whereas the alternatives are > consistent with one behaviour and inconsistent with the other. Then > again, with 'returns thingC' and 'returns returntype of put method', > the inconsistent behaviour is silent, puzzler-esque, and going to > cause hundreds of people subtle and hard to find bugs, whereas in the > 'returns void' scenario, there is no confusion at all, as the > compiler/editor will instantly tell you that the assignment is a > statement and not an expression. > > > I just talked myself into throwing my overwhelming support behind the > return void choice. Both other choices lead to long bug hunts and > confusion that can only be solved by experimenting or grabbing the > JLS, whereas void can't lead to bug hunts and any confusion it > engenders is instantly assuaged by a compiler hint. > > --Reinier Zwitserloot > > > > On 2009/23/06, at 07:46, Joseph D. Darcy wrote: > >> My current preference is to keep a simple desugaring of the indexing >> operators into method calls. While collection usage would certainly >> be a common case, there are probably other to-be-written APIs that >> would benefit from the translation into method calls. >> >> -Joe >> >> Reinier Zwitserloot wrote: >>> I agree that the expression "map[c] = d" returning the OLD value of >>> map[c] (e.g. usually null) is unacceptable behaviour, but I think >>> this propsoal would fare just fine if this form of operation is >>> defined to return void and not 'd', in order to avoid confusion. >>> There are many code bases that never use pass-through assignment, >>> and the workaround (write it out...) is by definition not more >>> boilerplate and noise than what we have now. >>> >>> >>> I do lean slightly to preferring the expression to return 'd', and >>> not void, nor 'old mapping of c'. >>> >>> --Reinier Zwitserloot >>> >>> >>> >>> On 2009/22/06, at 22:40, Lawrence Kesteloot wrote: >>> >>> >>>> On Mon, Jun 22, 2009 at 12:19 PM, Joseph D. >>>> Darcy wrote: >>>> >>>>> map["a"] = map["b"] = "c"; >>>>> >>>>> the new value for key "a" would be the old mapping of "b" and not >>>>> necessarily "c" because a call to the put method returns the old >>>>> value. >>>>> >>>> There is no way that: >>>> >>>> map["b"] = "c" >>>> >>>> can return anything other than "c". Returning the old value or >>>> returning void would violate 40 years of C-based expectations >>>> (including the identical construct in the STL). It must either return >>>> "c" or not be implemented at all. >>>> >>>> Lawrence >>>> >>>> >>> >>> >>> >> > From Joe.Darcy at Sun.COM Tue Jun 23 11:12:14 2009 From: Joe.Darcy at Sun.COM (Joseph D. Darcy) Date: Tue, 23 Jun 2009 11:12:14 -0700 Subject: Indexing access for Lists and Maps considered harmful? In-Reply-To: <15e8b9d20906231052j7d55c943m4bbe81284a854b1a@mail.gmail.com> References: <4A40DFBE.6030204@gmail.com> <4A411289.30808@sun.com> <15e8b9d20906231052j7d55c943m4bbe81284a854b1a@mail.gmail.com> Message-ID: <4A411AFE.8010600@sun.com> Neal Gafter wrote: > Why would a language-support method like Puttable.put return a value > that the generated code is required to ignore? I am not proposing that the value is required to be ignored. My current thinking is that compiler warnings are sufficient to deal with the multiple assignment situation in indexed access. Aggregates outside java.util.Collection could choose to be Puttable to avoid having to return some value. -Joe > From the point of view of designing a language-support API, it makes > no sense whatsoever. The return type is vestigal: it is only present > because of the way that we are considering retrofitting it onto some > existing APIs, but it forces any new APIs that are retrofitted to > return some (arbitrary) value to be ignored. It also imposes a > performance penalty on implementations that can more efficiently > overwrite a mapping than overwrite AND return the old value. This is > a language-design smell that suggests we should consider finding > another strategy for getting the effect of index operators. > > On Tue, Jun 23, 2009 at 10:36 AM, Joseph D. Darcy > wrote: > > spamolovko wrote: > > [snip] > > > > PS i remember that coin project had discussion about usage of > special > > interface for "indexing access". That interface have to use it's own > > methods for access to data, so no problems with get semantic. > > > > Example: > > > > public interface Indexer { > > > > public ValueType indexGet(KeyType key); > > > > public void indexSet(KeyType key, ValueType value); > > > > } > > > > [snip] > > The idea would be to retrofit new superinterfaces onto the List > and Map > interfaces without adding new methods to the interfaces. For example, > here is a slight refinement of strawman interfaces of that sort > from my > JavaOne talk: > > // New superinterfaces to indicate syntax? > interface GettableFromInt { > E get(int); > } > > interface Gettable { > V get(K k); > } > > interface Settable { > E set(int, E e); > } > interface Puttable { > V put(K k, V v); > } > > java.util.List extends GettableFromInt, Settable, ? > > java.util.Map extends Gettable, Puttable(K, V), ? > > The names "Gettable" etc. are open to improvement :-) > > -Joe > > From neal at gafter.com Tue Jun 23 11:20:41 2009 From: neal at gafter.com (Neal Gafter) Date: Tue, 23 Jun 2009 11:20:41 -0700 Subject: Indexing access for Lists and Maps considered harmful? In-Reply-To: <4A411AFE.8010600@sun.com> References: <4A40DFBE.6030204@gmail.com> <4A411289.30808@sun.com> <15e8b9d20906231052j7d55c943m4bbe81284a854b1a@mail.gmail.com> <4A411AFE.8010600@sun.com> Message-ID: <15e8b9d20906231120k657ae0e5m3a21c1e8cea49914@mail.gmail.com> On Tue, Jun 23, 2009 at 11:12 AM, Joseph D. Darcy wrote: > Neal Gafter wrote: > >> Why would a language-support method like Puttable.put return a value that >> the generated code is required to ignore? >> > > I am not proposing that the value is required to be ignored. My current > thinking is that compiler warnings are sufficient to deal with the multiple > assignment situation in indexed access. Aggregates outside > java.util.Collection could choose to be Puttable to > avoid having to return some value. That still requires the implementation to return something to be ignored (null), and is not parallel the the language's existing semantics for assignment expressions. From jjb at google.com Tue Jun 23 11:29:58 2009 From: jjb at google.com (Joshua Bloch) Date: Tue, 23 Jun 2009 11:29:58 -0700 Subject: Indexing access for Lists and Maps considered harmful? In-Reply-To: <63b4e4050906221233n1c1640c5tceff160a72140319@mail.gmail.com> References: <4A3FD954.6020709@sun.com> <63b4e4050906221233n1c1640c5tceff160a72140319@mail.gmail.com> Message-ID: <17b2302a0906231129l725786a7nd988cae9f937e7d4@mail.gmail.com> Folks, Hi. Sorry I'm late to the party; I'm just recovering from a pretty bad cold. I agree that this is not a showstopper. I think it's *critical* that the behavior be defined to match the "expected" behavior. These *must* function identically: myArray[i] = myArray[j] = val; myList[i] = myList[j] = val; When extending a language, it's critical to enable reasoning by analogy; to do otherwise *will* cause bugs and ill-will. (See this 20-year-old paper for my take on the topic: http://ieeexplore.ieee.org/xpls/abs_all.jsp?arnumber=37945 .) Josh On Mon, Jun 22, 2009 at 12:33 PM, Tim Peierls wrote: > Cool way to do swap and cyclic shift without temporaries: > m[a] = m[b] = m[c] = m[a]; > > I love it! Can I have it, can I, huh? :-) > > Seriously, I don't think this is a showstopper. > > --tim > > On Mon, Jun 22, 2009 at 3:19 PM, Joseph D. Darcy > wrote: > > > Hello. > > > > A recent blog post cited in Alex Miller's handy "Java 7 Links" > > (http://java7.tumblr.com) claims that adding indexing support for Lists > > and Maps would be harmful because of an arguably surprising behavior on > > compound assignment. After > > > > map["a"] = map["b"] = "c"; > > > > the new value for key "a" would be the old mapping of "b" and not > > necessarily "c" because a call to the put method returns the old value. > > > > I'm not too concerned about this interaction because compound assignment > > is relatively infrequent; however, I think a lint warning from the > > compiler would be appropriate in this case. Also, an IDE could color > > the non-array uses of "[]" differently to highlight any potential > > differences in semantics. > > > > As a meta-comment, I find it odd that if someone wanted to inform the > > coin discussion he or she would not directly email the coin list in > > addition to or instead of posting a blog entry. > > > > -Joe > > > > > > From forax at univ-mlv.fr Tue Jun 23 11:40:37 2009 From: forax at univ-mlv.fr (=?windows-1252?Q?R=E9mi_Forax?=) Date: Tue, 23 Jun 2009 20:40:37 +0200 Subject: Indexing access for Lists and Maps considered harmful? In-Reply-To: <4A411AFE.8010600@sun.com> References: <4A40DFBE.6030204@gmail.com> <4A411289.30808@sun.com> <15e8b9d20906231052j7d55c943m4bbe81284a854b1a@mail.gmail.com> <4A411AFE.8010600@sun.com> Message-ID: <4A4121A5.2060604@univ-mlv.fr> Joseph D. Darcy a ?crit : > Neal Gafter wrote: > >> Why would a language-support method like Puttable.put return a value >> that the generated code is required to ignore? >> > > I am not proposing that the value is required to be ignored. My current > thinking is that compiler warnings are sufficient to deal with the > multiple assignment situation in indexed access. Please, no more warning, warnings are not a clear signal for an average Joe. I am against the use of interfaces like Gettable/Puttable because you will have to rely on generics which doesn't mix well with primitive types. Some people that are fan of Trove : http://trove4j.sourceforge.net/index.html R?mi > Aggregates outside > java.util.Collection could choose to be Puttable to > avoid having to return some value. > > -Joe > > >> From the point of view of designing a language-support API, it makes >> no sense whatsoever. The return type is vestigal: it is only present >> because of the way that we are considering retrofitting it onto some >> existing APIs, but it forces any new APIs that are retrofitted to >> return some (arbitrary) value to be ignored. It also imposes a >> performance penalty on implementations that can more efficiently >> overwrite a mapping than overwrite AND return the old value. This is >> a language-design smell that suggests we should consider finding >> another strategy for getting the effect of index operators. >> >> On Tue, Jun 23, 2009 at 10:36 AM, Joseph D. Darcy > > wrote: >> >> spamolovko wrote: >> >> [snip] >> > >> > PS i remember that coin project had discussion about usage of >> special >> > interface for "indexing access". That interface have to use it's own >> > methods for access to data, so no problems with get semantic. >> > >> > Example: >> > >> > public interface Indexer { >> > >> > public ValueType indexGet(KeyType key); >> > >> > public void indexSet(KeyType key, ValueType value); >> > >> > } >> > >> >> [snip] >> >> The idea would be to retrofit new superinterfaces onto the List >> and Map >> interfaces without adding new methods to the interfaces. For example, >> here is a slight refinement of strawman interfaces of that sort >> from my >> JavaOne talk: >> >> // New superinterfaces to indicate syntax? >> interface GettableFromInt { >> E get(int); >> } >> >> interface Gettable { >> V get(K k); >> } >> >> interface Settable { >> E set(int, E e); >> } >> interface Puttable { >> V put(K k, V v); >> } >> >> java.util.List extends GettableFromInt, Settable, ? >> >> java.util.Map extends Gettable, Puttable(K, V), ? >> >> The names "Gettable" etc. are open to improvement :-) >> >> -Joe >> >> >> > > > From reinier at zwitserloot.com Tue Jun 23 12:27:59 2009 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Tue, 23 Jun 2009 21:27:59 +0200 Subject: Indexing access for Lists and Maps considered harmful? In-Reply-To: <4A4118BD.8090802@adres.pl> References: <4A40DFBE.6030204@gmail.com> <4A411289.30808@sun.com> <4A4118BD.8090802@adres.pl> Message-ID: Yes, Artur, I expect there will be very many classes that implement one but not the other. Immutables for the win. As this is going to be a 'magic interface', in a sense, in that the JLS explicitly refers to that exact interface (similar to how java.lang.Iterable is magic) it has to be 'right', from now until perpetuity. The current java collections API is fundamentally not designed with immutability in mind (a design that works with mutable/ immutable probably has a List superinterface that has only getter methods, then an ImmutableList subinterface that's used as marker, and a MutableList that adds the setters, or some such) - unlike Iterable and the proposed AllowGetAccess (or whatever it ends up being called) - the Java collections API is not part of the JLS, and some people have indeed switched to other collections APIs, such as google's, or even javac's own internal cons-style List version which is used extensively in javac instead of ArrayList and friends. --Reinier Zwitserloot On 2009/23/06, at 20:02, Artur Biesiadowski wrote: > Joseph D. Darcy wrote: >> // New superinterfaces to indicate syntax? >> interface GettableFromInt { >> E get(int); >> } >> >> interface Gettable { >> V get(K k); >> } >> >> interface Settable { >> E set(int, E e); >> } >> interface Puttable { >> V put(K k, V v); >> } >> > If anything like that is implemented, I would rather see it as two > interfaces - ListAccess and MapAccess (or maybe IndexAccess and > Key/DictionaryAccess to be less collection-oriented?). Read-only or > write-only classes can throw runtime exceptions if needed. > > Do you think that one-operation classes would be common? I can see a > possible benefit of detecting this at compile time instead of runtime, > but how useful it would be in real world... > > All collection classes would be read-write (even for immutable > collections no way to indicate it on interface level). > String could be probably made 'GettableFromInt'. > StringBuilder/Buffer is already read-write. Same goes for BitSet. > > I think it boils down to question if we want to have > > String txt = "ABC"; > txt[0] = 'X'; > > failing at compile time or runtime. On the other hand, in case of > String, I could imagine most IDEs making it a warning at compile time > easily... > > Regards, > Artur Biesiadowski > From scolebourne at joda.org Tue Jun 23 13:23:32 2009 From: scolebourne at joda.org (Stephen Colebourne) Date: Tue, 23 Jun 2009 21:23:32 +0100 Subject: Indexing access for Lists and Maps considered harmful? In-Reply-To: <17b2302a0906231129l725786a7nd988cae9f937e7d4@mail.gmail.com> References: <4A3FD954.6020709@sun.com> <63b4e4050906221233n1c1640c5tceff160a72140319@mail.gmail.com> <17b2302a0906231129l725786a7nd988cae9f937e7d4@mail.gmail.com> Message-ID: <4A4139C4.7050701@joda.org> Joshua Bloch wrote: > I think it's *critical* that the behavior be defined to match the "expected" > behavior. These *must* function identically: > > myArray[i] = myArray[j] = val; > > myList[i] = myList[j] = val; +1. I find this essential. Stephen From shams.mahmood at gmail.com Tue Jun 23 13:55:54 2009 From: shams.mahmood at gmail.com (Shams Mahmood) Date: Tue, 23 Jun 2009 15:55:54 -0500 Subject: Indexing access for Lists and Maps considered harmful? Message-ID: <36c722e00906231355v28598bc7kc12280275564bec1@mail.gmail.com> I'm late to join the party too (at the mailing list). One of my responses to the blog post was as follows: A method of maintaining the consistency and backwards compatibility could be to implement utility methods in say for e.g. Collections class: public static V get(Gettable pObject, K pKey) {?} public static V set(Puttable pObject, K pKey, V pNewValue) {?} public static V set(Map pObject, K pKey, V pNewValue) {?} public static V get(GettableFromInt pObject, int pIndex) {?} public static V set(SettableViaInt pObject, int pIndex, V pNewValue) {?} public static V set(List pObject, int pIndex, V pNewValue) {?} and also have Maps implementing Gettable and Puttable and Lists implementing GettableFromInt and SettableViaInt. The compiler will translate appropriately to corresponding method calls during compilation. This solution can easily be extended to have support for custom classes with the indexing access if they implement the appropriate interfaces. Reading furter discussion here, probably IndexedAccess and DictionaryAccess interfaces will do the trick with special utility methods for List and Map to wrap around the set/put methods So the new methods would be: public static V get(DictionaryAccess pObject, K pKey) {?} public static V set(DictionaryAccess pObject, K pKey, V pNewValue) {?} public static V get(IndexedAccess pObject, int pIndex) {?} public static V set(IndexedAccess pObject, int pIndex, V pNewValue) {?} e.g. public static V set(IndexedAccess pObject, int pIndex, V pNewValue) { pObject.set(pIndex, pNewValue); return pNewValue; } So, List list = new ArrayList(); list[1] = list[0] = "value"; would get translated to: Collections.set(list, 1, Collections.set(list, 0, "value")) Shams > ---------- Forwarded message ---------- > From: Artur Biesiadowski > To: coin-dev > Date: Tue, 23 Jun 2009 20:02:37 +0200 > Subject: Re: Indexing access for Lists and Maps considered harmful? > Joseph D. Darcy wrote: > >> // New superinterfaces to indicate syntax? >> interface GettableFromInt { >> E get(int); >> } >> >> interface Gettable { >> V get(K k); >> } >> >> interface Settable { >> E set(int, E e); >> } >> interface Puttable { >> V put(K k, V v); >> } >> >> > If anything like that is implemented, I would rather see it as two > interfaces - ListAccess and MapAccess (or maybe IndexAccess and > Key/DictionaryAccess to be less collection-oriented?). Read-only or > write-only classes can throw runtime exceptions if needed. > > Do you think that one-operation classes would be common? I can see a > possible benefit of detecting this at compile time instead of runtime, but > how useful it would be in real world... > > All collection classes would be read-write (even for immutable collections > no way to indicate it on interface level). > String could be probably made 'GettableFromInt'. > StringBuilder/Buffer is already read-write. Same goes for BitSet. > > I think it boils down to question if we want to have > > String txt = "ABC"; > txt[0] = 'X'; > > failing at compile time or runtime. On the other hand, in case of String, I > could imagine most IDEs making it a warning at compile time easily... > > Regards, > Artur Biesiadowski > > > > ---------- Forwarded message ---------- > From: "Joseph D. Darcy" > To: Reinier Zwitserloot > Date: Tue, 23 Jun 2009 11:06:20 -0700 > Subject: Re: Indexing access for Lists and Maps considered harmful? > Reinier Zwitserloot wrote: > >> You realize this is going to be an instant java puzzler, right? I thought >> one of the soft goals of project coin is to attempt to sidestep obvious >> puzzlers. >> > > It may be the case that changing the desugaring to return void in these > cases is the right thing to do in the end. > > However, the mere existence of *some* puzzler should not be sufficient to > derail a coin proposal. I fully expect the language changes to enable new, > initially unexpected program behavior; that does have to be more than > compensated by the new, expected programs behavior that is allowed of course > :-) > > -Joe > > >> I also admit that I cannot come up with any situation where the >> expression: >> >> thingA[thingB] = thingC; >> >> evaluating to something that ISNT 'thingC' (or void) is going to be the >> logical, not confusing choice. >> >> >> Suggestion: Define this operation to return void regardless of the >> underlying method implementation's actual return value. That way, if in the >> future a solid use case for letting the method invocation decide return type >> and value is found, a change can be made without breaking old code. If, on >> the other hand, there's a clamour for letting this expression return >> 'thingC', that can be added to a future version of java as well. >> >> In other words, picking EITHER "That evaluates to thingC" OR "That >> evaluates to whatever the put method returns" is a choice you must make for >> the rest of the life of the java language. On the other hand, picking "That >> is a statement and not an expression (e.g. evaluates to void)" is not a >> life-long choice; if it ends up being a bad choice, you can switch to either >> alternative later without any pain other than filing a purely additive >> language change. >> >> >> The only obvious disadvantage to 'return void' that I can see is that its >> inconsistent with both the current behaviour of the assignment operator AND >> the desugaring idea, whereas the alternatives are consistent with one >> behaviour and inconsistent with the other. Then again, with 'returns thingC' >> and 'returns returntype of put method', the inconsistent behaviour is >> silent, puzzler-esque, and going to cause hundreds of people subtle and hard >> to find bugs, whereas in the 'returns void' scenario, there is no confusion >> at all, as the compiler/editor will instantly tell you that the assignment >> is a statement and not an expression. >> >> >> I just talked myself into throwing my overwhelming support behind the >> return void choice. Both other choices lead to long bug hunts and confusion >> that can only be solved by experimenting or grabbing the JLS, whereas void >> can't lead to bug hunts and any confusion it engenders is instantly assuaged >> by a compiler hint. >> >> --Reinier Zwitserloot >> >> >> >> On 2009/23/06, at 07:46, Joseph D. Darcy wrote: >> >> My current preference is to keep a simple desugaring of the indexing >>> operators into method calls. While collection usage would certainly be a >>> common case, there are probably other to-be-written APIs that would benefit >>> from the translation into method calls. >>> >>> -Joe >>> >>> Reinier Zwitserloot wrote: >>> >>>> I agree that the expression "map[c] = d" returning the OLD value of >>>> map[c] (e.g. usually null) is unacceptable behaviour, but I think this >>>> propsoal would fare just fine if this form of operation is defined to >>>> return void and not 'd', in order to avoid confusion. There are many code >>>> bases that never use pass-through assignment, and the workaround (write it >>>> out...) is by definition not more boilerplate and noise than what we have >>>> now. >>>> >>>> >>>> I do lean slightly to preferring the expression to return 'd', and not >>>> void, nor 'old mapping of c'. >>>> >>>> --Reinier Zwitserloot >>>> >>>> >>>> >>>> On 2009/22/06, at 22:40, Lawrence Kesteloot wrote: >>>> >>>> >>>> On Mon, Jun 22, 2009 at 12:19 PM, Joseph D. Darcy >>>>> wrote: >>>>> >>>>> map["a"] = map["b"] = "c"; >>>>>> >>>>>> the new value for key "a" would be the old mapping of "b" and not >>>>>> necessarily "c" because a call to the put method returns the old >>>>>> value. >>>>>> >>>>>> There is no way that: >>>>> >>>>> map["b"] = "c" >>>>> >>>>> can return anything other than "c". Returning the old value or >>>>> returning void would violate 40 years of C-based expectations >>>>> (including the identical construct in the STL). It must either return >>>>> "c" or not be implemented at all. >>>>> >>>>> Lawrence >>>>> >>>>> >>>>> >>>> >>>> >>>> >>> >> > > > > ---------- Forwarded message ---------- > From: "Joseph D. Darcy" > To: Neal Gafter > Date: Tue, 23 Jun 2009 11:12:14 -0700 > Subject: Re: Indexing access for Lists and Maps considered harmful? > Neal Gafter wrote: > >> Why would a language-support method like Puttable.put return a value that >> the generated code is required to ignore? >> > > I am not proposing that the value is required to be ignored. My current > thinking is that compiler warnings are sufficient to deal with the multiple > assignment situation in indexed access. Aggregates outside > java.util.Collection could choose to be Puttable to > avoid having to return some value. > > -Joe > > From the point of view of designing a language-support API, it makes no >> sense whatsoever. The return type is vestigal: it is only present because >> of the way that we are considering retrofitting it onto some existing APIs, >> but it forces any new APIs that are retrofitted to return some (arbitrary) >> value to be ignored. It also imposes a performance penalty on >> implementations that can more efficiently overwrite a mapping than overwrite >> AND return the old value. This is a language-design smell that suggests we >> should consider finding another strategy for getting the effect of index >> operators. >> >> On Tue, Jun 23, 2009 at 10:36 AM, Joseph D. Darcy > Joe.Darcy at sun.com>> wrote: >> >> spamolovko wrote: >> >> [snip] >> > >> > PS i remember that coin project had discussion about usage of >> special >> > interface for "indexing access". That interface have to use it's own >> > methods for access to data, so no problems with get semantic. >> > >> > Example: >> > >> > public interface Indexer { >> > >> > public ValueType indexGet(KeyType key); >> > >> > public void indexSet(KeyType key, ValueType value); >> > >> > } >> > >> >> [snip] >> >> The idea would be to retrofit new superinterfaces onto the List >> and Map >> interfaces without adding new methods to the interfaces. For example, >> here is a slight refinement of strawman interfaces of that sort >> from my >> JavaOne talk: >> >> // New superinterfaces to indicate syntax? >> interface GettableFromInt { >> E get(int); >> } >> >> interface Gettable { >> V get(K k); >> } >> >> interface Settable { >> E set(int, E e); >> } >> interface Puttable { >> V put(K k, V v); >> } >> >> java.util.List extends GettableFromInt, Settable, ? >> >> java.util.Map extends Gettable, Puttable(K, V), ? >> >> The names "Gettable" etc. are open to improvement :-) >> >> -Joe >> >> >> > > > > ---------- Forwarded message ---------- > From: Neal Gafter > To: "Joseph D. Darcy" > Date: Tue, 23 Jun 2009 11:20:41 -0700 > Subject: Re: Indexing access for Lists and Maps considered harmful? > On Tue, Jun 23, 2009 at 11:12 AM, Joseph D. Darcy > wrote: > > > Neal Gafter wrote: > > > >> Why would a language-support method like Puttable.put return a value > that > >> the generated code is required to ignore? > >> > > > > I am not proposing that the value is required to be ignored. My current > > thinking is that compiler warnings are sufficient to deal with the > multiple > > assignment situation in indexed access. Aggregates outside > > java.util.Collection could choose to be Puttable to > > avoid having to return some value. > > > That still requires the implementation to return something to be ignored > (null), and is not parallel the the language's existing semantics for > assignment expressions. > > > > ---------- Forwarded message ---------- > From: Joshua Bloch > To: coin-dev > Date: Tue, 23 Jun 2009 11:29:58 -0700 > Subject: Re: Indexing access for Lists and Maps considered harmful? > Folks, > > Hi. Sorry I'm late to the party; I'm just recovering from a pretty bad > cold. > > I agree that this is not a showstopper. > > I think it's *critical* that the behavior be defined to match the > "expected" > behavior. These *must* function identically: > > myArray[i] = myArray[j] = val; > > myList[i] = myList[j] = val; > > When extending a language, it's critical to enable reasoning by analogy; to > do otherwise *will* cause bugs and ill-will. (See this 20-year-old paper > for my take on the topic: > http://ieeexplore.ieee.org/xpls/abs_all.jsp?arnumber=37945 .) > > Josh > > > > On Mon, Jun 22, 2009 at 12:33 PM, Tim Peierls wrote: > > > Cool way to do swap and cyclic shift without temporaries: > > m[a] = m[b] = m[c] = m[a]; > > > > I love it! Can I have it, can I, huh? :-) > > > > Seriously, I don't think this is a showstopper. > > > > --tim > > > > On Mon, Jun 22, 2009 at 3:19 PM, Joseph D. Darcy > > wrote: > > > > > Hello. > > > > > > A recent blog post cited in Alex Miller's handy "Java 7 Links" > > > (http://java7.tumblr.com) claims that adding indexing support for > Lists > > > and Maps would be harmful because of an arguably surprising behavior on > > > compound assignment. After > > > > > > map["a"] = map["b"] = "c"; > > > > > > the new value for key "a" would be the old mapping of "b" and not > > > necessarily "c" because a call to the put method returns the old value. > > > > > > I'm not too concerned about this interaction because compound > assignment > > > is relatively infrequent; however, I think a lint warning from the > > > compiler would be appropriate in this case. Also, an IDE could color > > > the non-array uses of "[]" differently to highlight any potential > > > differences in semantics. > > > > > > As a meta-comment, I find it odd that if someone wanted to inform the > > > coin discussion he or she would not directly email the coin list in > > > addition to or instead of posting a blog entry. > > > > > > -Joe > > > > > > > > > > > > > > ---------- Forwarded message ---------- > From: "R?mi Forax" > To: "Joseph D. Darcy" > Date: Tue, 23 Jun 2009 20:40:37 +0200 > Subject: Re: Indexing access for Lists and Maps considered harmful? > Joseph D. Darcy a ?crit : > >> Neal Gafter wrote: >> >> >>> Why would a language-support method like Puttable.put return a value that >>> the generated code is required to ignore? >>> >> >> I am not proposing that the value is required to be ignored. My current >> thinking is that compiler warnings are sufficient to deal with the multiple >> assignment situation in indexed access. >> > > Please, no more warning, warnings are not a clear signal for an average > Joe. > > I am against the use of interfaces like Gettable/Puttable because you will > have to > rely on generics which doesn't mix well with primitive types. > > Some people that are fan of Trove : > http://trove4j.sourceforge.net/index.html > > R?mi > > Aggregates outside java.util.Collection could choose to be >> Puttable to avoid having to return some value. >> >> -Joe >> >> >> >>> From the point of view of designing a language-support API, it makes no >>> sense whatsoever. The return type is vestigal: it is only present because >>> of the way that we are considering retrofitting it onto some existing APIs, >>> but it forces any new APIs that are retrofitted to return some (arbitrary) >>> value to be ignored. It also imposes a performance penalty on >>> implementations that can more efficiently overwrite a mapping than overwrite >>> AND return the old value. This is a language-design smell that suggests we >>> should consider finding another strategy for getting the effect of index >>> operators. >>> >>> On Tue, Jun 23, 2009 at 10:36 AM, Joseph D. Darcy >> Joe.Darcy at sun.com>> wrote: >>> >>> spamolovko wrote: >>> >>> [snip] >>> > >>> > PS i remember that coin project had discussion about usage of >>> special >>> > interface for "indexing access". That interface have to use it's own >>> > methods for access to data, so no problems with get semantic. >>> > >>> > Example: >>> > >>> > public interface Indexer { >>> > >>> > public ValueType indexGet(KeyType key); >>> > >>> > public void indexSet(KeyType key, ValueType value); >>> > >>> > } >>> > >>> >>> [snip] >>> >>> The idea would be to retrofit new superinterfaces onto the List >>> and Map >>> interfaces without adding new methods to the interfaces. For example, >>> here is a slight refinement of strawman interfaces of that sort >>> from my >>> JavaOne talk: >>> >>> // New superinterfaces to indicate syntax? >>> interface GettableFromInt { >>> E get(int); >>> } >>> >>> interface Gettable { >>> V get(K k); >>> } >>> >>> interface Settable { >>> E set(int, E e); >>> } >>> interface Puttable { >>> V put(K k, V v); >>> } >>> >>> java.util.List extends GettableFromInt, Settable, ? >>> >>> java.util.Map extends Gettable, Puttable(K, V), ? >>> >>> The names "Gettable" etc. are open to improvement :-) >>> >>> -Joe >>> >>> >>> >>> >> >> >> >> > > > > -- Shams Mahmood From neal at gafter.com Tue Jun 23 14:42:40 2009 From: neal at gafter.com (Neal Gafter) Date: Tue, 23 Jun 2009 14:42:40 -0700 Subject: Indexing access for Lists and Maps considered harmful? In-Reply-To: <36c722e00906231355v28598bc7kc12280275564bec1@mail.gmail.com> References: <36c722e00906231355v28598bc7kc12280275564bec1@mail.gmail.com> Message-ID: <15e8b9d20906231442q4db305f4l5db912f1a651e68e@mail.gmail.com> On Tue, Jun 23, 2009 at 1:55 PM, Shams Mahmood wrote: > So, > List list = new ArrayList(); > list[1] = list[0] = "value"; > would get translated to: > Collections.set(list, 1, Collections.set(list, 0, "value")) The link to methods in Collections is a bit too magical (e.g. it won't gracefully handle anything other than the collections API nor will it gracefully support evolution of the platform). From java.net at twistedprotein.com Tue Jun 23 15:29:24 2009 From: java.net at twistedprotein.com (Brendon McLean) Date: Wed, 24 Jun 2009 00:29:24 +0200 Subject: Indexing access for Lists and Maps considered harmful? In-Reply-To: <17b2302a0906231129l725786a7nd988cae9f937e7d4@mail.gmail.com> References: <4A3FD954.6020709@sun.com> <63b4e4050906221233n1c1640c5tceff160a72140319@mail.gmail.com> <17b2302a0906231129l725786a7nd988cae9f937e7d4@mail.gmail.com> Message-ID: On 23 Jun 2009, at 20:29, Joshua Bloch wrote: > I think it's *critical* that the behavior be defined to match the > "expected" > behavior. These *must* function identically: > > myArray[i] = myArray[j] = val; > > myList[i] = myList[j] = val; > > When extending a language, it's critical to enable reasoning by > analogy; to > do otherwise *will* cause bugs and ill-will. (See this 20-year-old > paper > for my take on the topic: > http://ieeexplore.ieee.org/xpls/abs_all.jsp?arnumber=37945 .) 100% agree here. Array/list equivalence is logical, expected and intuitive. Surely the point of the syntactic sugar to make this so? Brendon McLean. From shams.mahmood at gmail.com Tue Jun 23 16:35:21 2009 From: shams.mahmood at gmail.com (Shams Mahmood) Date: Tue, 23 Jun 2009 16:35:21 -0700 (PDT) Subject: Indexing access for Lists and Maps considered harmful? In-Reply-To: <15e8b9d20906231442q4db305f4l5db912f1a651e68e@mail.gmail.com> References: <36c722e00906231355v28598bc7kc12280275564bec1@mail.gmail.com> <15e8b9d20906231442q4db305f4l5db912f1a651e68e@mail.gmail.com> Message-ID: <564879.729.qm@web112516.mail.gq1.yahoo.com> I don't follow why it won't handle anything other than the collections api.The compiler should be able to support any implementations of IndexedAccess and DictionaryAccess just like the for each loop handles any implementations of the Iterable interface. ________________________________ From: Neal Gafter To: Shams Mahmood Cc: coin-dev at openjdk.java.net Sent: Tuesday, June 23, 2009 4:42:40 PM Subject: Re: Indexing access for Lists and Maps considered harmful? On Tue, Jun 23, 2009 at 1:55 PM, Shams Mahmood wrote: > >So, >>List list = new ArrayList(); >>list[1] = list[0] = "value"; >>would get translated to: >>Collections.set(list, 1, Collections.set(list, 0, "value")) The link to methods in Collections is a bit too magical (e.g. it won't gracefully handle anything other than the collections API nor will it gracefully support evolution of the platform). From neal at gafter.com Tue Jun 23 17:47:34 2009 From: neal at gafter.com (Neal Gafter) Date: Tue, 23 Jun 2009 17:47:34 -0700 Subject: Indexing access for Lists and Maps considered harmful? In-Reply-To: <564879.729.qm@web112516.mail.gq1.yahoo.com> References: <36c722e00906231355v28598bc7kc12280275564bec1@mail.gmail.com> <15e8b9d20906231442q4db305f4l5db912f1a651e68e@mail.gmail.com> <564879.729.qm@web112516.mail.gq1.yahoo.com> Message-ID: <15e8b9d20906231747y41260ea9g875ed74d721dad61@mail.gmail.com> These methods are language-support methods. If I create a new array-like API, what should its "put" method return? Four choices are void, null, the input value, or the logical value placed into the data structure. void doesn't work because that's not the return type of the method in these interfaces. null is silly (an API method that should always return nothing should be declared void), and conflicts with the JLS's meaning of an assignment expression (see below). The input value isn't correct; the value resulting from the assignment is supposed to be the NEW value in that variable (JLS3 15.26 paragraph 3). For built-in arrays, that is the value converted to the array element type. For general collection-like APIs, the result of an assignment using the array syntax may be some other "equivalent" value (for example, strings might be interned). To support the JLS semantics, the API needs to have an opportunity to yield this value. So IndexedAccess.put() should be declared to return a value of type V, which should be specified to be *the value of the logical variable after the assignment has occurred*. java.util.List, on the other hand, has a put method that is declared with the right signature (it returns a V), but it returns the wrong value to support the JLS semantics for assignment. Retrofitting interfaces onto existing classes is a poor solution to this language-design problem. Regards, Neal On Tue, Jun 23, 2009 at 4:35 PM, Shams Mahmood wrote: > I don't follow why it won't handle anything other than the collections api. > The compiler should be able to support any implementations of > IndexedAccess and DictionaryAccess just like the for each loop > handles any implementations of the Iterable interface. > > > > ------------------------------ > *From:* Neal Gafter > *To:* Shams Mahmood > *Cc:* coin-dev at openjdk.java.net > *Sent:* Tuesday, June 23, 2009 4:42:40 PM > *Subject:* Re: Indexing access for Lists and Maps considered harmful? > > On Tue, Jun 23, 2009 at 1:55 PM, Shams Mahmood wrote: > >> So, >> List list = new ArrayList(); >> list[1] = list[0] = "value"; >> would get translated to: >> Collections.set(list, 1, Collections.set(list, 0, "value")) > > > The link to methods in Collections is a bit too magical (e.g. it won't > gracefully handle anything other than the collections API nor will it > gracefully support evolution of the platform). > > > From reinier at zwitserloot.com Tue Jun 23 18:39:18 2009 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Wed, 24 Jun 2009 03:39:18 +0200 Subject: Indexing access for Lists and Maps considered harmful? In-Reply-To: <15e8b9d20906231747y41260ea9g875ed74d721dad61@mail.gmail.com> References: <36c722e00906231355v28598bc7kc12280275564bec1@mail.gmail.com> <15e8b9d20906231442q4db305f4l5db912f1a651e68e@mail.gmail.com> <564879.729.qm@web112516.mail.gq1.yahoo.com> <15e8b9d20906231747y41260ea9g875ed74d721dad61@mail.gmail.com> Message-ID: I agree to the theory of your post, but, so what? Java is not going to be perfect unless java is willing to sacrifice backwards compatibility, which it isn't. So, perfection can't be the goal - because if it is, then no language change is ever going to make it in, and paradoxically, that really brings java no closer to perfection. So - so what that it isn't perfect? Let's roll with where I think you are trying to go, and create 2 interfaces, where the SetIndex semantics are defined as requiring the implementing class to return the logical value - e.g. boxing a primitive when assigning it into a list, for example. But now we can't retrofit java.util.List without breaking thousands of List implementations out there, so the conclusion would have to be that you can not use a List itself; you must use either a specific type (such as ArrayList, retrofitted to implement SetIndex), or a newly created List2 interface that also implements SetIndex. In this scenario, I'm assuming the name of the method isn't set(), as that would conflict with java.util.List's set which has different semantics. So, riddle me this then. There are 3 java7 scenarios: In the first scenario, m[a] = m[b] = c; does what you want, but only if m is an ArrayList, SetIndex, or HashMap. It just doesn't work if m is a List or Map type. Even for just "m[b] = c", which I'll bet is more prevalent than m[a] = m[b] = c by a factor of 100 or more! In the second scenario, m[a] = m[b] = c does not do what you want (and in my opinion, should express this by failing fast - generating a compiler error on the spot stating that m[b] = c is not an expression, but that's not relevant to the point I'm trying to make here) - but it works with every type you'd expect it to work with: List, Map, arrays, and many other types of objects. In the third scenario, m[a] = c isn't allowed at all. In the fourth scenario, java complicates the process quite a bit e.g. by having a scala-esque conversion semantic where some class in the classpath has registered itself as capable of turning any java.util.List into a java.lang.SetIndex object. m[a] = m[b] =c does what you want, and it works with List, but now the proposal is rather complicated. I'm quite certain the (vast?) majority will go with the second java7. If pass-through assignment was more common than it is, it might be worth investigating the fourth scenario more thoroughly, NB: I'd hereby like to repeat my suggestion to choose pragmatism over perfection here: Returning void is pragmatic, in that we can always change it later without breaking any code. In this case, the pragmatic choice may have to be to define explicitly SetIndex behaviour as existing for java.util.List and java.util.Map and no other types of objects (hard code the types, at least for now - no need to do this to GetIndex, as there are no issues there). If these things are sorted out in the future, then the restriction can be waived, and any code can use it. It may not be /pretty/, but it has the crucial advantage of being future-compatible! --Reinier Zwitserloot On 2009/24/06, at 02:47, Neal Gafter wrote: > These methods are language-support methods. If I create a new array- > like > API, what should its "put" method return? Four choices are void, > null, the > input value, or the logical value placed into the data structure. > > void doesn't work because that's not the return type of the method > in these > interfaces. > > null is silly (an API method that should always return nothing > should be > declared void), and conflicts with the JLS's meaning of an assignment > expression (see below). > > The input value isn't correct; the value resulting from the > assignment is > supposed to be the NEW value in that variable (JLS3 15.26 paragraph > 3). For > built-in arrays, that is the value converted to the array element > type. > > For general collection-like APIs, the result of an assignment using > the > array syntax may be some other "equivalent" value (for example, > strings > might be interned). To support the JLS semantics, the API needs to > have an > opportunity to yield this value. So IndexedAccess.put() should be > declared to return a value of type V, which should be specified to > be *the > value of the logical variable after the assignment has occurred*. > java.util.List, on the other hand, has a put method that is declared > with > the right signature (it returns a V), but it returns the wrong value > to > support the JLS semantics for assignment. > > Retrofitting interfaces onto existing classes is a poor solution to > this > language-design problem. > > Regards, > Neal > > On Tue, Jun 23, 2009 at 4:35 PM, Shams Mahmood >wrote: > >> I don't follow why it won't handle anything other than the >> collections api. >> The compiler should be able to support any implementations of >> IndexedAccess and DictionaryAccess just like the for each >> loop >> handles any implementations of the Iterable interface. >> >> >> >> ------------------------------ >> *From:* Neal Gafter >> *To:* Shams Mahmood >> *Cc:* coin-dev at openjdk.java.net >> *Sent:* Tuesday, June 23, 2009 4:42:40 PM >> *Subject:* Re: Indexing access for Lists and Maps considered harmful? >> >> On Tue, Jun 23, 2009 at 1:55 PM, Shams Mahmood > >wrote: >> >>> So, >>> List list = new ArrayList(); >>> list[1] = list[0] = "value"; >>> would get translated to: >>> Collections.set(list, 1, Collections.set(list, 0, "value")) >> >> >> The link to methods in Collections is a bit too magical (e.g. it >> won't >> gracefully handle anything other than the collections API nor will it >> gracefully support evolution of the platform). >> >> >> > From jjb at google.com Tue Jun 23 20:40:52 2009 From: jjb at google.com (Joshua Bloch) Date: Tue, 23 Jun 2009 20:40:52 -0700 Subject: Indexing access for Lists and Maps considered harmful? In-Reply-To: References: <36c722e00906231355v28598bc7kc12280275564bec1@mail.gmail.com> <15e8b9d20906231442q4db305f4l5db912f1a651e68e@mail.gmail.com> <564879.729.qm@web112516.mail.gq1.yahoo.com> <15e8b9d20906231747y41260ea9g875ed74d721dad61@mail.gmail.com> Message-ID: <17b2302a0906232040x4adf6894s55eab1d13e2c29a0@mail.gmail.com> Reinier, I don't really understand your post. What's wrong with just agreeing at the outset that a[i] = b[i] = x; works, and then figuring out what (if any) interfaces we need to make it work? Josh On Tue, Jun 23, 2009 at 6:39 PM, Reinier Zwitserloot < reinier at zwitserloot.com> wrote: > I agree to the theory of your post, but, so what? > > Java is not going to be perfect unless java is willing to sacrifice > backwards compatibility, which it isn't. So, perfection can't be the > goal - because if it is, then no language change is ever going to make > it in, and paradoxically, that really brings java no closer to > perfection. > > So - so what that it isn't perfect? Let's roll with where I think you > are trying to go, and create 2 interfaces, where the SetIndex > semantics are defined as requiring the implementing class to return > the logical value - e.g. boxing a primitive when assigning it into a > list, for example. > > But now we can't retrofit java.util.List without breaking thousands of > List implementations out there, so the conclusion would have to be > that you can not use a List itself; you must use either a specific > type (such as ArrayList, retrofitted to implement SetIndex), or a > newly created List2 interface that also implements SetIndex. In this > scenario, I'm assuming the name of the method isn't set(), as that > would conflict with java.util.List's set which has different semantics. > > So, riddle me this then. There are 3 java7 scenarios: > > In the first scenario, m[a] = m[b] = c; does what you want, but only > if m is an ArrayList, SetIndex, or HashMap. It just doesn't work if m > is a List or Map type. Even for just "m[b] = c", which I'll bet is > more prevalent than m[a] = m[b] = c by a factor of 100 or more! > > In the second scenario, m[a] = m[b] = c does not do what you want (and > in my opinion, should express this by failing fast - generating a > compiler error on the spot stating that m[b] = c is not an expression, > but that's not relevant to the point I'm trying to make here) - but it > works with every type you'd expect it to work with: List, Map, arrays, > and many other types of objects. > > In the third scenario, m[a] = c isn't allowed at all. > > In the fourth scenario, java complicates the process quite a bit e.g. > by having a scala-esque conversion semantic where some class in the > classpath has registered itself as capable of turning any > java.util.List into a java.lang.SetIndex object. m[a] = m[b] =c does > what you want, and it works with List, but now the proposal is rather > complicated. > > I'm quite certain the (vast?) majority will go with the second java7. > If pass-through assignment was more common than it is, it might be > worth investigating the fourth scenario more thoroughly, > > NB: I'd hereby like to repeat my suggestion to choose pragmatism over > perfection here: Returning void is pragmatic, in that we can always > change it later without breaking any code. In this case, the pragmatic > choice may have to be to define explicitly SetIndex behaviour as > existing for java.util.List and java.util.Map and no other types of > objects (hard code the types, at least for now - no need to do this to > GetIndex, as there are no issues there). If these things are sorted > out in the future, then the restriction can be waived, and any code > can use it. It may not be /pretty/, but it has the crucial advantage > of being future-compatible! > > --Reinier Zwitserloot > > > > On 2009/24/06, at 02:47, Neal Gafter wrote: > > > These methods are language-support methods. If I create a new array- > > like > > API, what should its "put" method return? Four choices are void, > > null, the > > input value, or the logical value placed into the data structure. > > > > void doesn't work because that's not the return type of the method > > in these > > interfaces. > > > > null is silly (an API method that should always return nothing > > should be > > declared void), and conflicts with the JLS's meaning of an assignment > > expression (see below). > > > > The input value isn't correct; the value resulting from the > > assignment is > > supposed to be the NEW value in that variable (JLS3 15.26 paragraph > > 3). For > > built-in arrays, that is the value converted to the array element > > type. > > > > For general collection-like APIs, the result of an assignment using > > the > > array syntax may be some other "equivalent" value (for example, > > strings > > might be interned). To support the JLS semantics, the API needs to > > have an > > opportunity to yield this value. So IndexedAccess.put() should be > > declared to return a value of type V, which should be specified to > > be *the > > value of the logical variable after the assignment has occurred*. > > java.util.List, on the other hand, has a put method that is declared > > with > > the right signature (it returns a V), but it returns the wrong value > > to > > support the JLS semantics for assignment. > > > > Retrofitting interfaces onto existing classes is a poor solution to > > this > > language-design problem. > > > > Regards, > > Neal > > > > On Tue, Jun 23, 2009 at 4:35 PM, Shams Mahmood > >wrote: > > > >> I don't follow why it won't handle anything other than the > >> collections api. > >> The compiler should be able to support any implementations of > >> IndexedAccess and DictionaryAccess just like the for each > >> loop > >> handles any implementations of the Iterable interface. > >> > >> > >> > >> ------------------------------ > >> *From:* Neal Gafter > >> *To:* Shams Mahmood > >> *Cc:* coin-dev at openjdk.java.net > >> *Sent:* Tuesday, June 23, 2009 4:42:40 PM > >> *Subject:* Re: Indexing access for Lists and Maps considered harmful? > >> > >> On Tue, Jun 23, 2009 at 1:55 PM, Shams Mahmood >> >wrote: > >> > >>> So, > >>> List list = new ArrayList(); > >>> list[1] = list[0] = "value"; > >>> would get translated to: > >>> Collections.set(list, 1, Collections.set(list, 0, "value")) > >> > >> > >> The link to methods in Collections is a bit too magical (e.g. it > >> won't > >> gracefully handle anything other than the collections API nor will it > >> gracefully support evolution of the platform). > >> > >> > >> > > > > > From reinier at zwitserloot.com Tue Jun 23 21:38:59 2009 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Wed, 24 Jun 2009 06:38:59 +0200 Subject: Indexing access for Lists and Maps considered harmful? In-Reply-To: <17b2302a0906232040x4adf6894s55eab1d13e2c29a0@mail.gmail.com> References: <36c722e00906231355v28598bc7kc12280275564bec1@mail.gmail.com> <15e8b9d20906231442q4db305f4l5db912f1a651e68e@mail.gmail.com> <564879.729.qm@web112516.mail.gq1.yahoo.com> <15e8b9d20906231747y41260ea9g875ed74d721dad61@mail.gmail.com> <17b2302a0906232040x4adf6894s55eab1d13e2c29a0@mail.gmail.com> Message-ID: <56B5CBBF-DEDA-4361-92CA-68B61AA60CEE@zwitserloot.com> It's not just a matter of figuring out "what interfaces we need to make this work" - at least, with Neal's semantics. I'm making the assumption that "a[x] = b" should be legal where x is an integer, a is a java.util.List, and b is a T. That's obvious - that's the goal of this proposal in the first place. Neal's semantics and the way java.util.List is designed makes it impossible to address this issue by way of an interface. You'd need to hardcode the meaning of a[b] = c for at least java.util.List, if you want Neal's semantics. At the same time, Neal's semantics, while almost impossible to implement, are essentially correct, in that they are the most compatible of all the various proposals with how pass-through assignment works today in java6. Conclusion: I think we need to move away from being 100% consistent in an area (pass-through assignment) that almost nobody uses. It's not worth either complicating the proposal or delaying it, just to get to this mythical 100% consistency, especially considering that we can always add it later if we roll with 'a[b] = c is not an expression but a statement, when it involves SetIndex desugaring' now. --Reinier Zwitserloot On 2009/24/06, at 05:40, Joshua Bloch wrote: > Reinier, > > I don't really understand your post. What's wrong with just > agreeing at the outset that a[i] = b[i] = x; works, and then > figuring out what (if any) interfaces we need to make it work? > > Josh > > On Tue, Jun 23, 2009 at 6:39 PM, Reinier Zwitserloot > wrote: > I agree to the theory of your post, but, so what? > > Java is not going to be perfect unless java is willing to sacrifice > backwards compatibility, which it isn't. So, perfection can't be the > goal - because if it is, then no language change is ever going to make > it in, and paradoxically, that really brings java no closer to > perfection. > > So - so what that it isn't perfect? Let's roll with where I think you > are trying to go, and create 2 interfaces, where the SetIndex > semantics are defined as requiring the implementing class to return > the logical value - e.g. boxing a primitive when assigning it into a > list, for example. > > But now we can't retrofit java.util.List without breaking thousands of > List implementations out there, so the conclusion would have to be > that you can not use a List itself; you must use either a specific > type (such as ArrayList, retrofitted to implement SetIndex), or a > newly created List2 interface that also implements SetIndex. In this > scenario, I'm assuming the name of the method isn't set(), as that > would conflict with java.util.List's set which has different > semantics. > > So, riddle me this then. There are 3 java7 scenarios: > > In the first scenario, m[a] = m[b] = c; does what you want, but only > if m is an ArrayList, SetIndex, or HashMap. It just doesn't work if m > is a List or Map type. Even for just "m[b] = c", which I'll bet is > more prevalent than m[a] = m[b] = c by a factor of 100 or more! > > In the second scenario, m[a] = m[b] = c does not do what you want (and > in my opinion, should express this by failing fast - generating a > compiler error on the spot stating that m[b] = c is not an expression, > but that's not relevant to the point I'm trying to make here) - but it > works with every type you'd expect it to work with: List, Map, arrays, > and many other types of objects. > > In the third scenario, m[a] = c isn't allowed at all. > > In the fourth scenario, java complicates the process quite a bit e.g. > by having a scala-esque conversion semantic where some class in the > classpath has registered itself as capable of turning any > java.util.List into a java.lang.SetIndex object. m[a] = m[b] =c does > what you want, and it works with List, but now the proposal is rather > complicated. > > I'm quite certain the (vast?) majority will go with the second java7. > If pass-through assignment was more common than it is, it might be > worth investigating the fourth scenario more thoroughly, > > NB: I'd hereby like to repeat my suggestion to choose pragmatism over > perfection here: Returning void is pragmatic, in that we can always > change it later without breaking any code. In this case, the pragmatic > choice may have to be to define explicitly SetIndex behaviour as > existing for java.util.List and java.util.Map and no other types of > objects (hard code the types, at least for now - no need to do this to > GetIndex, as there are no issues there). If these things are sorted > out in the future, then the restriction can be waived, and any code > can use it. It may not be /pretty/, but it has the crucial advantage > of being future-compatible! > > --Reinier Zwitserloot > > > > On 2009/24/06, at 02:47, Neal Gafter wrote: > > > These methods are language-support methods. If I create a new > array- > > like > > API, what should its "put" method return? Four choices are void, > > null, the > > input value, or the logical value placed into the data structure. > > > > void doesn't work because that's not the return type of the method > > in these > > interfaces. > > > > null is silly (an API method that should always return nothing > > should be > > declared void), and conflicts with the JLS's meaning of an > assignment > > expression (see below). > > > > The input value isn't correct; the value resulting from the > > assignment is > > supposed to be the NEW value in that variable (JLS3 15.26 paragraph > > 3). For > > built-in arrays, that is the value converted to the array element > > type. > > > > For general collection-like APIs, the result of an assignment using > > the > > array syntax may be some other "equivalent" value (for example, > > strings > > might be interned). To support the JLS semantics, the API needs to > > have an > > opportunity to yield this value. So IndexedAccess.put() should > be > > declared to return a value of type V, which should be specified to > > be *the > > value of the logical variable after the assignment has occurred*. > > java.util.List, on the other hand, has a put method that is declared > > with > > the right signature (it returns a V), but it returns the wrong value > > to > > support the JLS semantics for assignment. > > > > Retrofitting interfaces onto existing classes is a poor solution to > > this > > language-design problem. > > > > Regards, > > Neal > > > > On Tue, Jun 23, 2009 at 4:35 PM, Shams Mahmood > >wrote: > > > >> I don't follow why it won't handle anything other than the > >> collections api. > >> The compiler should be able to support any implementations of > >> IndexedAccess and DictionaryAccess just like the for each > >> loop > >> handles any implementations of the Iterable interface. > >> > >> > >> > >> ------------------------------ > >> *From:* Neal Gafter > >> *To:* Shams Mahmood > >> *Cc:* coin-dev at openjdk.java.net > >> *Sent:* Tuesday, June 23, 2009 4:42:40 PM > >> *Subject:* Re: Indexing access for Lists and Maps considered > harmful? > >> > >> On Tue, Jun 23, 2009 at 1:55 PM, Shams Mahmood >> >wrote: > >> > >>> So, > >>> List list = new ArrayList(); > >>> list[1] = list[0] = "value"; > >>> would get translated to: > >>> Collections.set(list, 1, Collections.set(list, 0, "value")) > >> > >> > >> The link to methods in Collections is a bit too magical (e.g. it > >> won't > >> gracefully handle anything other than the collections API nor > will it > >> gracefully support evolution of the platform). > >> > >> > >> > > > > > From lk at teamten.com Tue Jun 23 22:26:54 2009 From: lk at teamten.com (Lawrence Kesteloot) Date: Tue, 23 Jun 2009 22:26:54 -0700 Subject: Indexing access for Lists and Maps considered harmful? In-Reply-To: <56B5CBBF-DEDA-4361-92CA-68B61AA60CEE@zwitserloot.com> References: <36c722e00906231355v28598bc7kc12280275564bec1@mail.gmail.com> <15e8b9d20906231442q4db305f4l5db912f1a651e68e@mail.gmail.com> <564879.729.qm@web112516.mail.gq1.yahoo.com> <15e8b9d20906231747y41260ea9g875ed74d721dad61@mail.gmail.com> <17b2302a0906232040x4adf6894s55eab1d13e2c29a0@mail.gmail.com> <56B5CBBF-DEDA-4361-92CA-68B61AA60CEE@zwitserloot.com> Message-ID: <997cab100906232226u221e512el29a5c9cf36a802b@mail.gmail.com> Reinier, I don't buy the argument that the compile error makes returning void acceptable. Programmers won't realize that the construct "a[b] = c" isn't a real assignment and won't understand why they get a cryptic error when they write: do { x = read(); } while ((list[i++] = x) != terminatingValue); They'll fight with it for a while before deciding that Java is just mysteriously inconsistent. This consideration, in my opinion, trumps arguments about library implementation elegance or efficiency. Besides, if the code is indeed a hot spot, the process of inlining will recognize the needless handling of the old value and remove it. (If it's not a hot spot then it's doesn't matter.) Neal's argument about the ability to return an "equivalent" object is valid. Something has to give, that I would pick that. It's reasonable in nearly all cases to just return the RHS object. Lawrence On Tue, Jun 23, 2009 at 9:38 PM, Reinier Zwitserloot wrote: > It's not just a matter of figuring out "what interfaces we need to > make this work" - at least, with Neal's semantics. I'm making the > assumption that "a[x] = b" should be legal where x is an integer, a is > a java.util.List, and b is a T. That's obvious - that's the goal of > this proposal in the first place. Neal's semantics and the way > java.util.List is designed makes it impossible to address this issue > by way of an interface. You'd need to hardcode the meaning of a[b] = c > for at least java.util.List, if you want Neal's semantics. > > At the same time, Neal's semantics, while almost impossible to > implement, are essentially correct, in that they are the most > compatible of all the various proposals with how pass-through > assignment works today in java6. > > Conclusion: I think we need to move away from being 100% consistent in > an area (pass-through assignment) that almost nobody uses. It's not > worth either complicating the proposal or delaying it, just to get to > this mythical 100% consistency, especially considering that we can > always add it later if we roll with 'a[b] = c is not an expression but > a statement, when it involves SetIndex desugaring' now. > > > ?--Reinier Zwitserloot > > > > On 2009/24/06, at 05:40, Joshua Bloch wrote: > >> Reinier, >> >> I don't really understand your post. ?What's wrong with just >> agreeing at the outset that a[i] = b[i] = x; works, and then >> figuring out what (if any) interfaces we need to make it work? >> >> ? ? ? ? ?Josh >> >> On Tue, Jun 23, 2009 at 6:39 PM, Reinier Zwitserloot > > wrote: >> I agree to the theory of your post, but, so what? >> >> Java is not going to be perfect unless java is willing to sacrifice >> backwards compatibility, which it isn't. So, perfection can't be the >> goal - because if it is, then no language change is ever going to make >> it in, and paradoxically, that really brings java no closer to >> perfection. >> >> So - so what that it isn't perfect? Let's roll with where I think you >> are trying to go, and create 2 interfaces, where the SetIndex >> semantics are defined as requiring the implementing class to return >> the logical value - e.g. boxing a primitive when assigning it into a >> list, for example. >> >> But now we can't retrofit java.util.List without breaking thousands of >> List implementations out there, so the conclusion would have to be >> that you can not use a List itself; you must use either a specific >> type (such as ArrayList, retrofitted to implement SetIndex), or a >> newly created List2 interface that also implements SetIndex. In this >> scenario, I'm assuming the name of the method isn't set(), as that >> would conflict with java.util.List's set which has different >> semantics. >> >> So, riddle me this then. There are 3 java7 scenarios: >> >> In the first scenario, m[a] = m[b] = c; does what you want, but only >> if m is an ArrayList, SetIndex, or HashMap. It just doesn't work if m >> is a List or Map type. Even for just "m[b] = c", which I'll bet is >> more prevalent than m[a] = m[b] = c by a factor of 100 or more! >> >> In the second scenario, m[a] = m[b] = c does not do what you want (and >> in my opinion, should express this by failing fast - generating a >> compiler error on the spot stating that m[b] = c is not an expression, >> but that's not relevant to the point I'm trying to make here) - but it >> works with every type you'd expect it to work with: List, Map, arrays, >> and many other types of objects. >> >> In the third scenario, m[a] = c isn't allowed at all. >> >> In the fourth scenario, java complicates the process quite a bit e.g. >> by having a scala-esque conversion semantic where some class in the >> classpath has registered itself as capable of turning any >> java.util.List into a java.lang.SetIndex object. m[a] = m[b] =c does >> what you want, and it works with List, but now the proposal is rather >> complicated. >> >> I'm quite certain the (vast?) majority will go with the second java7. >> If pass-through assignment was more common than it is, it might be >> worth investigating the fourth scenario more thoroughly, >> >> NB: I'd hereby like to repeat my suggestion to choose pragmatism over >> perfection here: Returning void is pragmatic, in that we can always >> change it later without breaking any code. In this case, the pragmatic >> choice may have to be to define explicitly SetIndex behaviour as >> existing for java.util.List and java.util.Map and no other types of >> objects (hard code the types, at least for now - no need to do this to >> GetIndex, as there are no issues there). If these things are sorted >> out in the future, then the restriction can be waived, and any code >> can use it. It may not be /pretty/, but it has the crucial advantage >> of being future-compatible! >> >> ?--Reinier Zwitserloot >> >> >> >> On 2009/24/06, at 02:47, Neal Gafter wrote: >> >> > These methods are language-support methods. ?If I create a new >> array- >> > like >> > API, what should its "put" method return? ?Four choices are void, >> > null, the >> > input value, or the logical value placed into the data structure. >> > >> > void doesn't work because that's not the return type of the method >> > in these >> > interfaces. >> > >> > null is silly (an API method that should always return nothing >> > should be >> > declared void), and conflicts with the JLS's meaning of an >> assignment >> > expression (see below). >> > >> > The input value isn't correct; the value resulting from the >> > assignment is >> > supposed to be the NEW value in that variable (JLS3 15.26 paragraph >> > 3). ?For >> > built-in arrays, that is the value converted to the array element >> > type. >> > >> > For general collection-like APIs, the result of an assignment using >> > the >> > array syntax may be some other "equivalent" value (for example, >> > strings >> > might be interned). ?To support the JLS semantics, the API needs to >> > have an >> > opportunity to yield this value. ?So IndexedAccess.put() should >> be >> > declared to return a value of type V, which should be specified to >> > be *the >> > value of the logical variable after the assignment has occurred*. >> > java.util.List, on the other hand, has a put method that is declared >> > with >> > the right signature (it returns a V), but it returns the wrong value >> > to >> > support the JLS semantics for assignment. >> > >> > Retrofitting interfaces onto existing classes is a poor solution to >> > this >> > language-design problem. >> > >> > Regards, >> > Neal >> > >> > On Tue, Jun 23, 2009 at 4:35 PM, Shams Mahmood > > >wrote: >> > >> >> I don't follow why it won't handle anything other than the >> >> collections api. >> >> The compiler should be able to support any implementations of >> >> IndexedAccess and DictionaryAccess just like the for each >> >> loop >> >> handles any implementations of the Iterable interface. >> >> >> >> >> >> >> >> ------------------------------ >> >> *From:* Neal Gafter >> >> *To:* Shams Mahmood >> >> *Cc:* coin-dev at openjdk.java.net >> >> *Sent:* Tuesday, June 23, 2009 4:42:40 PM >> >> *Subject:* Re: Indexing access for Lists and Maps considered >> harmful? >> >> >> >> On Tue, Jun 23, 2009 at 1:55 PM, Shams Mahmood > >> >wrote: >> >> >> >>> So, >> >>> List list = new ArrayList(); >> >>> list[1] = list[0] = "value"; >> >>> would get translated to: >> >>> Collections.set(list, 1, Collections.set(list, 0, "value")) >> >> >> >> >> >> The link to methods in Collections is a bit too magical (e.g. it >> >> won't >> >> gracefully handle anything other than the collections API nor >> will it >> >> gracefully support evolution of the platform). >> >> >> >> >> >> >> > >> >> >> > > > From Joe.Darcy at Sun.COM Tue Jun 23 22:33:03 2009 From: Joe.Darcy at Sun.COM (Joseph D. Darcy) Date: Tue, 23 Jun 2009 22:33:03 -0700 Subject: Indexing access for Lists and Maps considered harmful? In-Reply-To: <17b2302a0906232040x4adf6894s55eab1d13e2c29a0@mail.gmail.com> References: <36c722e00906231355v28598bc7kc12280275564bec1@mail.gmail.com> <15e8b9d20906231442q4db305f4l5db912f1a651e68e@mail.gmail.com> <564879.729.qm@web112516.mail.gq1.yahoo.com> <15e8b9d20906231747y41260ea9g875ed74d721dad61@mail.gmail.com> <17b2302a0906232040x4adf6894s55eab1d13e2c29a0@mail.gmail.com> Message-ID: <4A41BA8F.8090407@sun.com> A less than ideal option would be to just support [] access for getting and not setting, but I think we can work out something acceptable for setting as well. -Joe Joshua Bloch wrote: > Reinier, > I don't really understand your post. What's wrong with just agreeing at the > outset that a[i] = b[i] = x; works, and then figuring out what (if any) > interfaces we need to make it work? > > Josh > > On Tue, Jun 23, 2009 at 6:39 PM, Reinier Zwitserloot < > reinier at zwitserloot.com> wrote: > > >> I agree to the theory of your post, but, so what? >> >> Java is not going to be perfect unless java is willing to sacrifice >> backwards compatibility, which it isn't. So, perfection can't be the >> goal - because if it is, then no language change is ever going to make >> it in, and paradoxically, that really brings java no closer to >> perfection. >> >> So - so what that it isn't perfect? Let's roll with where I think you >> are trying to go, and create 2 interfaces, where the SetIndex >> semantics are defined as requiring the implementing class to return >> the logical value - e.g. boxing a primitive when assigning it into a >> list, for example. >> >> But now we can't retrofit java.util.List without breaking thousands of >> List implementations out there, so the conclusion would have to be >> that you can not use a List itself; you must use either a specific >> type (such as ArrayList, retrofitted to implement SetIndex), or a >> newly created List2 interface that also implements SetIndex. In this >> scenario, I'm assuming the name of the method isn't set(), as that >> would conflict with java.util.List's set which has different semantics. >> >> So, riddle me this then. There are 3 java7 scenarios: >> >> In the first scenario, m[a] = m[b] = c; does what you want, but only >> if m is an ArrayList, SetIndex, or HashMap. It just doesn't work if m >> is a List or Map type. Even for just "m[b] = c", which I'll bet is >> more prevalent than m[a] = m[b] = c by a factor of 100 or more! >> >> In the second scenario, m[a] = m[b] = c does not do what you want (and >> in my opinion, should express this by failing fast - generating a >> compiler error on the spot stating that m[b] = c is not an expression, >> but that's not relevant to the point I'm trying to make here) - but it >> works with every type you'd expect it to work with: List, Map, arrays, >> and many other types of objects. >> >> In the third scenario, m[a] = c isn't allowed at all. >> >> In the fourth scenario, java complicates the process quite a bit e.g. >> by having a scala-esque conversion semantic where some class in the >> classpath has registered itself as capable of turning any >> java.util.List into a java.lang.SetIndex object. m[a] = m[b] =c does >> what you want, and it works with List, but now the proposal is rather >> complicated. >> >> I'm quite certain the (vast?) majority will go with the second java7. >> If pass-through assignment was more common than it is, it might be >> worth investigating the fourth scenario more thoroughly, >> >> NB: I'd hereby like to repeat my suggestion to choose pragmatism over >> perfection here: Returning void is pragmatic, in that we can always >> change it later without breaking any code. In this case, the pragmatic >> choice may have to be to define explicitly SetIndex behaviour as >> existing for java.util.List and java.util.Map and no other types of >> objects (hard code the types, at least for now - no need to do this to >> GetIndex, as there are no issues there). If these things are sorted >> out in the future, then the restriction can be waived, and any code >> can use it. It may not be /pretty/, but it has the crucial advantage >> of being future-compatible! >> >> --Reinier Zwitserloot >> >> >> >> On 2009/24/06, at 02:47, Neal Gafter wrote: >> >> >>> These methods are language-support methods. If I create a new array- >>> like >>> API, what should its "put" method return? Four choices are void, >>> null, the >>> input value, or the logical value placed into the data structure. >>> >>> void doesn't work because that's not the return type of the method >>> in these >>> interfaces. >>> >>> null is silly (an API method that should always return nothing >>> should be >>> declared void), and conflicts with the JLS's meaning of an assignment >>> expression (see below). >>> >>> The input value isn't correct; the value resulting from the >>> assignment is >>> supposed to be the NEW value in that variable (JLS3 15.26 paragraph >>> 3). For >>> built-in arrays, that is the value converted to the array element >>> type. >>> >>> For general collection-like APIs, the result of an assignment using >>> the >>> array syntax may be some other "equivalent" value (for example, >>> strings >>> might be interned). To support the JLS semantics, the API needs to >>> have an >>> opportunity to yield this value. So IndexedAccess.put() should be >>> declared to return a value of type V, which should be specified to >>> be *the >>> value of the logical variable after the assignment has occurred*. >>> java.util.List, on the other hand, has a put method that is declared >>> with >>> the right signature (it returns a V), but it returns the wrong value >>> to >>> support the JLS semantics for assignment. >>> >>> Retrofitting interfaces onto existing classes is a poor solution to >>> this >>> language-design problem. >>> >>> Regards, >>> Neal >>> >>> On Tue, Jun 23, 2009 at 4:35 PM, Shams Mahmood >> >>>> wrote: >>>> >>>> I don't follow why it won't handle anything other than the >>>> collections api. >>>> The compiler should be able to support any implementations of >>>> IndexedAccess and DictionaryAccess just like the for each >>>> loop >>>> handles any implementations of the Iterable interface. >>>> >>>> >>>> >>>> ------------------------------ >>>> *From:* Neal Gafter >>>> *To:* Shams Mahmood >>>> *Cc:* coin-dev at openjdk.java.net >>>> *Sent:* Tuesday, June 23, 2009 4:42:40 PM >>>> *Subject:* Re: Indexing access for Lists and Maps considered harmful? >>>> >>>> On Tue, Jun 23, 2009 at 1:55 PM, Shams Mahmood >>> >>>>> wrote: >>>>> >>>>> So, >>>>> List list = new ArrayList(); >>>>> list[1] = list[0] = "value"; >>>>> would get translated to: >>>>> Collections.set(list, 1, Collections.set(list, 0, "value")) >>>>> >>>> The link to methods in Collections is a bit too magical (e.g. it >>>> won't >>>> gracefully handle anything other than the collections API nor will it >>>> gracefully support evolution of the platform). >>>> >>>> >>>> >>>> >> >> > > From neal at gafter.com Tue Jun 23 22:55:54 2009 From: neal at gafter.com (Neal Gafter) Date: Tue, 23 Jun 2009 22:55:54 -0700 Subject: Indexing access for Lists and Maps considered harmful? In-Reply-To: References: <36c722e00906231355v28598bc7kc12280275564bec1@mail.gmail.com> <15e8b9d20906231442q4db305f4l5db912f1a651e68e@mail.gmail.com> <564879.729.qm@web112516.mail.gq1.yahoo.com> <15e8b9d20906231747y41260ea9g875ed74d721dad61@mail.gmail.com> Message-ID: <15e8b9d20906232255x7d690d3csbfa454d04c2d9902@mail.gmail.com> On Tue, Jun 23, 2009 at 6:39 PM, Reinier Zwitserloot < reinier at zwitserloot.com> wrote: > I agree to the theory of your post, but, so what? > > Java is not going to be perfect unless java is willing to sacrifice > backwards compatibility, which it isn't. So, perfection can't be the goal - > because if it is, then no language change is ever going to make it in, and > paradoxically, that really brings java no closer to perfection. So you're saying that because Java isn't perfect, we shouldn't bother trying for the best possible evolution of the language? Or do you really believe that the constraint of backward compatibility precludes a solution that satisfies all of our requirements? You've explored a small part of the design space involving the addition of new interfaces and found no solution that satisfies the requirements. Do you conclude therefore that a good solution doesn't exist? I've explored a slightly larger design space and found a few perfectly acceptable solutions that appear to satisfy all of our design criteria, but using different techniques than the ones you considered. My favorite solution is a combination of specification by syntactic translation and the addition of support for extension methods. It can be retrofitted onto any existing class or interface without breaking backward compatibility, and can be defined to have precisely the necessary semantics to match the JLS specification for assignment. > NB: I'd hereby like to repeat my suggestion to choose pragmatism over > perfection here: Sure, if there were a conflict between the two (there isn't) that would be reasonable. Adding direct support for the collection interfaces to the JLS isn't a reasonable approach either. Cheers, Neal From spamolovko at gmail.com Tue Jun 23 23:38:08 2009 From: spamolovko at gmail.com (spamolovko) Date: Wed, 24 Jun 2009 10:38:08 +0400 Subject: Indexing access for Lists and Maps considered harmful? In-Reply-To: <17b2302a0906231129l725786a7nd988cae9f937e7d4@mail.gmail.com> References: <4A3FD954.6020709@sun.com> <63b4e4050906221233n1c1640c5tceff160a72140319@mail.gmail.com> <17b2302a0906231129l725786a7nd988cae9f937e7d4@mail.gmail.com> Message-ID: <4A41C9D0.5030402@gmail.com> Hello. Joshua Bloch wrote: > Folks, > > Hi. Sorry I'm late to the party; I'm just recovering from a pretty bad > cold. > > I agree that this is not a showstopper. > > I think it's *critical* that the behavior be defined to match the "expected" > behavior. These *must* function identically: > > myArray[i] = myArray[j] = val; > > myList[i] = myList[j] = val; > +1, Totally agree with you. But many people in this mail list forget that "myList[i] = myList[j] = val;" have 3 operations. because it PUT val into myList[j], then GET from myList[j] and PUT it into myList[i]. Do not forget about getter!!! > When extending a language, it's critical to enable reasoning by analogy; to > do otherwise *will* cause bugs and ill-will. (See this 20-year-old paper > for my take on the topic: > http://ieeexplore.ieee.org/xpls/abs_all.jsp?arnumber=37945 .) > > Josh > > > From spamolovko at gmail.com Tue Jun 23 23:50:10 2009 From: spamolovko at gmail.com (spamolovko) Date: Wed, 24 Jun 2009 10:50:10 +0400 Subject: Indexing access for Lists and Maps considered harmful? In-Reply-To: References: <36c722e00906231355v28598bc7kc12280275564bec1@mail.gmail.com> <15e8b9d20906231442q4db305f4l5db912f1a651e68e@mail.gmail.com> <564879.729.qm@web112516.mail.gq1.yahoo.com> <15e8b9d20906231747y41260ea9g875ed74d721dad61@mail.gmail.com> Message-ID: <4A41CCA2.7010203@gmail.com> Reinier Zwitserloot wrote: > I agree to the theory of your post, but, so what? > > Java is not going to be perfect unless java is willing to sacrifice > backwards compatibility, which it isn't. So, perfection can't be the > goal - because if it is, then no language change is ever going to make > it in, and paradoxically, that really brings java no closer to > perfection. > Yes, that is true. I hope that Oracle will "sacrifice backwards compatibility" and implement features that are standard for other good languages. And being "non perfect" is not a reason to stop evolution. > So - so what that it isn't perfect? Let's roll with where I think you > are trying to go, and create 2 interfaces, where the SetIndex > semantics are defined as requiring the implementing class to return > the logical value - e.g. boxing a primitive when assigning it into a > list, for example. > > But now we can't retrofit java.util.List without breaking thousands of > List implementations out there, so the conclusion would have to be > that you can not use a List itself; you must use either a specific > type (such as ArrayList, retrofitted to implement SetIndex), or a > newly created List2 interface that also implements SetIndex. In this > scenario, I'm assuming the name of the method isn't set(), as that > would conflict with java.util.List's set which has different semantics. > public interface IndexedAccess { public ValueType indexGet(int key); public void indexSet(int key, ValueType value); } interface Collection extends Iterable, IndexedAccess and then just use: List list = new ... list[0] = "hello"; What is the problems here? > > --Reinier Zwitserloot > From ted at tedneward.com Tue Jun 23 23:52:56 2009 From: ted at tedneward.com (Ted Neward) Date: Tue, 23 Jun 2009 23:52:56 -0700 Subject: Indexing access for Lists and Maps considered harmful? In-Reply-To: <4A41CCA2.7010203@gmail.com> References: <36c722e00906231355v28598bc7kc12280275564bec1@mail.gmail.com> <15e8b9d20906231442q4db305f4l5db912f1a651e68e@mail.gmail.com> <564879.729.qm@web112516.mail.gq1.yahoo.com> <15e8b9d20906231747y41260ea9g875ed74d721dad61@mail.gmail.com> <4A41CCA2.7010203@gmail.com> Message-ID: <079701c9f498$7195aa50$54c0fef0$@com> > public interface IndexedAccess { > > public ValueType indexGet(int key); > > public void indexSet(int key, ValueType value); > > } > > interface Collection extends Iterable, IndexedAccess > > and then just use: > List list = new ... > list[0] = "hello"; > > What is the problems here? > For starters, assuming your implementation turns list[0] = "hello"; into list.indexSet(0, "hello"); which returns void, then the following list[0] = list[1] = "hello"; would fail: list.indexSet(0, list.indexSet(1, "hello")); // error! Cannot pass void as a parameter And that would break the existing Java semantics that have been there since 1.0. In your implementation, indexSet *must* return ValueType, and it must return the value passed in, if the existing semantics for Java are going to be preserved. Am I missing something here? If, as I think Neal already pointed out, we look at the expression a = b = c; The results of the intermediate expression "b = c" is "c", and therefore the results of the expression "a = (b = c)" is "c" as well. What are we arguing about? This is established Java language semantics, isn't it? Ted Neward | Principal Consultant, ThoughtWorks Java, .NET, XML Services Consulting, Teaching, Speaking, Writing http://www.thoughtworks.com | http://www.tedneward.com > -----Original Message----- > From: coin-dev-bounces at openjdk.java.net [mailto:coin-dev- > bounces at openjdk.java.net] On Behalf Of spamolovko > Sent: Tuesday, June 23, 2009 11:50 PM > To: Reinier Zwitserloot > Cc: coin-dev at openjdk.java.net > Subject: Re: Indexing access for Lists and Maps considered harmful? > > Reinier Zwitserloot wrote: > > I agree to the theory of your post, but, so what? > > > > Java is not going to be perfect unless java is willing to sacrifice > > backwards compatibility, which it isn't. So, perfection can't be the > > goal - because if it is, then no language change is ever going to > make > > it in, and paradoxically, that really brings java no closer to > > perfection. > > > Yes, that is true. I hope that Oracle will "sacrifice backwards > compatibility" and implement features that are standard for other good > languages. > > And being "non perfect" is not a reason to stop evolution. > > > So - so what that it isn't perfect? Let's roll with where I think you > > are trying to go, and create 2 interfaces, where the SetIndex > > semantics are defined as requiring the implementing class to return > > the logical value - e.g. boxing a primitive when assigning it into a > > list, for example. > > > > But now we can't retrofit java.util.List without breaking thousands > of > > List implementations out there, so the conclusion would have to be > > that you can not use a List itself; you must use either a specific > > type (such as ArrayList, retrofitted to implement SetIndex), or a > > newly created List2 interface that also implements SetIndex. In this > > scenario, I'm assuming the name of the method isn't set(), as that > > would conflict with java.util.List's set which has different > semantics. > > > public interface IndexedAccess { > > public ValueType indexGet(int key); > > public void indexSet(int key, ValueType value); > > } > > interface Collection extends Iterable, IndexedAccess > > and then just use: > List list = new ... > list[0] = "hello"; > > What is the problems here? > > > > --Reinier Zwitserloot > > From ted at tedneward.com Wed Jun 24 00:48:50 2009 From: ted at tedneward.com (Ted Neward) Date: Wed, 24 Jun 2009 00:48:50 -0700 Subject: Indexing access for Lists and Maps considered harmful? In-Reply-To: <4A41D69F.1090005@gmail.com> References: <36c722e00906231355v28598bc7kc12280275564bec1@mail.gmail.com> <15e8b9d20906231442q4db305f4l5db912f1a651e68e@mail.gmail.com> <564879.729.qm@web112516.mail.gq1.yahoo.com> <15e8b9d20906231747y41260ea9g875ed74d721dad61@mail.gmail.com> <4A41CCA2.7010203@gmail.com> <079701c9f498$7195aa50$54c0fef0$@com> <4A41D69F.1090005@gmail.com> Message-ID: <07aa01c9f4a0$3c6f4680$b54dd380$@com> Um.. I guess I assume that the getter would work as expected. I don't really care what the underlying code generated looks like, so long as the language semantics are upheld. Frankly, if the compiler wants to turn this: list[0] = list[1] = "hello"; into: T temp = "hello"; list.indexSet(1, temp); list.indexSet(0, temp); as opposed to: list.indexSet(1, "hello"); list.indexSet(0, list.indexGet(1)); on the grounds that the first version would be moderately faster, I could really care less. That's an implementation detail. The goal of any language enhancement should be to preserve existing language semantics even as it extends them. Ted Neward | Principal Consultant, ThoughtWorks Java, .NET, XML Services Consulting, Teaching, Speaking, Writing http://www.thoughtworks.com | http://www.tedneward.com From: spamolovko [mailto:spamolovko at gmail.com] Sent: Wednesday, June 24, 2009 12:33 AM To: Ted Neward Cc: 'Reinier Zwitserloot'; coin-dev at openjdk.java.net Subject: Re: Indexing access for Lists and Maps considered harmful? How must work "list[0] = list[1];"? this must work as: list.indexSet(0, list.indexGet(1)); So list[0] = list[1] = "hello"; must work same as semantically identical list[1] = "hello"; list[0] = list[1]; This mean that it would be translated into: list.indexSet(1, "hello"); list.indexSet(0, list.indexGet(1)); Why are you forgetting about GETTER? If you get anything from collection - you MUST use getter, not result from setter. That is JavaBeans semantic. PS do not use setter instead of getter and all will work fine. Ted Neward wrote: public interface IndexedAccess { public ValueType indexGet(int key); public void indexSet(int key, ValueType value); } interface Collection extends Iterable, IndexedAccess and then just use: List list = new ... list[0] = "hello"; What is the problems here? For starters, assuming your implementation turns list[0] = "hello"; into list.indexSet(0, "hello"); which returns void, then the following list[0] = list[1] = "hello"; would fail: list.indexSet(0, list.indexSet(1, "hello")); // error! Cannot pass void as a parameter And that would break the existing Java semantics that have been there since 1.0. In your implementation, indexSet *must* return ValueType, and it must return the value passed in, if the existing semantics for Java are going to be preserved. Am I missing something here? If, as I think Neal already pointed out, we look at the expression a = b = c; The results of the intermediate expression "b = c" is "c", and therefore the results of the expression "a = (b = c)" is "c" as well. What are we arguing about? This is established Java language semantics, isn't it? Ted Neward | Principal Consultant, ThoughtWorks Java, .NET, XML Services Consulting, Teaching, Speaking, Writing http://www.thoughtworks.com | http://www.tedneward.com From mthornton at optrak.co.uk Wed Jun 24 00:51:09 2009 From: mthornton at optrak.co.uk (Mark Thornton) Date: Wed, 24 Jun 2009 08:51:09 +0100 Subject: Indexing access for Lists and Maps considered harmful? In-Reply-To: <56B5CBBF-DEDA-4361-92CA-68B61AA60CEE@zwitserloot.com> References: <36c722e00906231355v28598bc7kc12280275564bec1@mail.gmail.com> <15e8b9d20906231442q4db305f4l5db912f1a651e68e@mail.gmail.com> <564879.729.qm@web112516.mail.gq1.yahoo.com> <15e8b9d20906231747y41260ea9g875ed74d721dad61@mail.gmail.com> <17b2302a0906232040x4adf6894s55eab1d13e2c29a0@mail.gmail.com> <56B5CBBF-DEDA-4361-92CA-68B61AA60CEE@zwitserloot.com> Message-ID: <4A41DAED.6010903@optrak.co.uk> Reinier Zwitserloot wrote: > Conclusion: I think we need to move away from being 100% consistent in > an area (pass-through assignment) that almost nobody uses. It's not > I use it. Admittedly not often, but it is there. After writing Java for about 12 years there probably isn't much that I haven't used at least once. Anyone else want to admit to using this? Regards from Almost Nobody, Mak Thornton From mthornton at optrak.co.uk Wed Jun 24 00:55:00 2009 From: mthornton at optrak.co.uk (Mark Thornton) Date: Wed, 24 Jun 2009 08:55:00 +0100 Subject: Indexing access for Lists and Maps considered harmful? In-Reply-To: <997cab100906232226u221e512el29a5c9cf36a802b@mail.gmail.com> References: <36c722e00906231355v28598bc7kc12280275564bec1@mail.gmail.com> <15e8b9d20906231442q4db305f4l5db912f1a651e68e@mail.gmail.com> <564879.729.qm@web112516.mail.gq1.yahoo.com> <15e8b9d20906231747y41260ea9g875ed74d721dad61@mail.gmail.com> <17b2302a0906232040x4adf6894s55eab1d13e2c29a0@mail.gmail.com> <56B5CBBF-DEDA-4361-92CA-68B61AA60CEE@zwitserloot.com> <997cab100906232226u221e512el29a5c9cf36a802b@mail.gmail.com> Message-ID: <4A41DBD4.2080306@optrak.co.uk> Lawrence Kesteloot wrote: > Neal's argument about the ability to return an "equivalent" object is > valid. Something has to give, that I would pick that. It's reasonable > in nearly all cases to just return the RHS object. > > If the RHS value is going to be boxed, I think it is important that it be boxed only once and not separately for each assignment. Mark Thornton From ted at tedneward.com Wed Jun 24 00:56:48 2009 From: ted at tedneward.com (Ted Neward) Date: Wed, 24 Jun 2009 00:56:48 -0700 Subject: Indexing access for Lists and Maps considered harmful? In-Reply-To: <4A41DAED.6010903@optrak.co.uk> References: <36c722e00906231355v28598bc7kc12280275564bec1@mail.gmail.com> <15e8b9d20906231442q4db305f4l5db912f1a651e68e@mail.gmail.com> <564879.729.qm@web112516.mail.gq1.yahoo.com> <15e8b9d20906231747y41260ea9g875ed74d721dad61@mail.gmail.com> <17b2302a0906232040x4adf6894s55eab1d13e2c29a0@mail.gmail.com> <56B5CBBF-DEDA-4361-92CA-68B61AA60CEE@zwitserloot.com> <4A41DAED.6010903@optrak.co.uk> Message-ID: <07ba01c9f4a1$5b319d60$1194d820$@com> No. I will strongly oppose any effort to "move away from 100% consistency", regardless of how many people on this list use a particular feature or if it's an area that "almost nobody uses". Languages have to be consistent, or developers' faith in that language begins to erode and the language itself begins to die. Anything less is irresponsible. Ted Neward | Principal Consultant, ThoughtWorks Java, .NET, XML Services Consulting, Teaching, Speaking, Writing http://www.thoughtworks.com | http://www.tedneward.com > -----Original Message----- > From: coin-dev-bounces at openjdk.java.net [mailto:coin-dev- > bounces at openjdk.java.net] On Behalf Of Mark Thornton > Sent: Wednesday, June 24, 2009 12:51 AM > To: Reinier Zwitserloot > Cc: coin-dev at openjdk.java.net > Subject: Re: Indexing access for Lists and Maps considered harmful? > > Reinier Zwitserloot wrote: > > Conclusion: I think we need to move away from being 100% consistent > in > > an area (pass-through assignment) that almost nobody uses. It's not > > > I use it. Admittedly not often, but it is there. After writing Java for > about 12 years there probably isn't much that I haven't used at least > once. > > Anyone else want to admit to using this? > > Regards from Almost Nobody, > Mak Thornton From mthornton at optrak.co.uk Wed Jun 24 01:02:37 2009 From: mthornton at optrak.co.uk (Mark Thornton) Date: Wed, 24 Jun 2009 09:02:37 +0100 Subject: Indexing access for Lists and Maps considered harmful? In-Reply-To: <079701c9f498$7195aa50$54c0fef0$@com> References: <36c722e00906231355v28598bc7kc12280275564bec1@mail.gmail.com> <15e8b9d20906231442q4db305f4l5db912f1a651e68e@mail.gmail.com> <564879.729.qm@web112516.mail.gq1.yahoo.com> <15e8b9d20906231747y41260ea9g875ed74d721dad61@mail.gmail.com> <4A41CCA2.7010203@gmail.com> <079701c9f498$7195aa50$54c0fef0$@com> Message-ID: <4A41DD9D.3080909@optrak.co.uk> Ted Neward wrote: > preserved. Am I missing something here? If, as I think Neal already pointed > out, we look at the expression > > a = b = c; > > The results of the intermediate expression "b = c" is "c", and therefore the > results of the expression "a = (b = c)" is "c" as well. What are we arguing > As I understand it, if c is a primitive and b is an object then the result of "b=c" is boxed(c). In addition b = boxed(c); a = boxed(c); does not necessarily give the same result as b = boxed(c); a = b; Regards, Mark Thornton From ted at tedneward.com Wed Jun 24 01:21:33 2009 From: ted at tedneward.com (Ted Neward) Date: Wed, 24 Jun 2009 01:21:33 -0700 Subject: Indexing access for Lists and Maps considered harmful? In-Reply-To: <4A41DD9D.3080909@optrak.co.uk> References: <36c722e00906231355v28598bc7kc12280275564bec1@mail.gmail.com> <15e8b9d20906231442q4db305f4l5db912f1a651e68e@mail.gmail.com> <564879.729.qm@web112516.mail.gq1.yahoo.com> <15e8b9d20906231747y41260ea9g875ed74d721dad61@mail.gmail.com> <4A41CCA2.7010203@gmail.com> <079701c9f498$7195aa50$54c0fef0$@com> <4A41DD9D.3080909@optrak.co.uk> Message-ID: <07c001c9f4a4$cd24ba80$676e2f80$@com> Under what situation would a = b = c (where b is boxed(c) ) yield different results? Aside from concurrency scenarios, my understanding is that boxed or not, the value is still "c", thus a would hold the value "c", boxed or otherwise. Note that of course concurrency/multi-threaded-access to a/b/c will change any of this; I'm assuming a single-threaded scenario here for simplicity's sake (and because my understanding is that this proposal is not suggesting that the language needs to take on additional atomicity guarantees beyond what is already defined by the JLS). Ted Neward | Principal Consultant, ThoughtWorks Java, .NET, XML Services Consulting, Teaching, Speaking, Writing http://www.thoughtworks.com | http://www.tedneward.com > -----Original Message----- > From: Mark Thornton [mailto:mthornton at optrak.co.uk] > Sent: Wednesday, June 24, 2009 1:03 AM > To: Ted Neward > Cc: coin-dev at openjdk.java.net > Subject: Re: Indexing access for Lists and Maps considered harmful? > > Ted Neward wrote: > > preserved. Am I missing something here? If, as I think Neal already > pointed > > out, we look at the expression > > > > a = b = c; > > > > The results of the intermediate expression "b = c" is "c", and > therefore the > > results of the expression "a = (b = c)" is "c" as well. What are we > arguing > > > As I understand it, if c is a primitive and b is an object then the > result of "b=c" is boxed(c). In addition > > b = boxed(c); > a = boxed(c); > > does not necessarily give the same result as > > b = boxed(c); > a = b; > > Regards, > Mark Thornton From ted at tedneward.com Wed Jun 24 01:22:50 2009 From: ted at tedneward.com (Ted Neward) Date: Wed, 24 Jun 2009 01:22:50 -0700 Subject: Indexing access for Lists and Maps considered harmful? In-Reply-To: <4A41DBD4.2080306@optrak.co.uk> References: <36c722e00906231355v28598bc7kc12280275564bec1@mail.gmail.com> <15e8b9d20906231442q4db305f4l5db912f1a651e68e@mail.gmail.com> <564879.729.qm@web112516.mail.gq1.yahoo.com> <15e8b9d20906231747y41260ea9g875ed74d721dad61@mail.gmail.com> <17b2302a0906232040x4adf6894s55eab1d13e2c29a0@mail.gmail.com> <56B5CBBF-DEDA-4361-92CA-68B61AA60CEE@zwitserloot.com> <997cab100906232226u221e512el29a5c9cf36a802b@mail.gmail.com> <4A41DBD4.2080306@optrak.co.uk> Message-ID: <07c101c9f4a4$fcff6660$f6fe3320$@com> Why? Boxed values are read-only values, last time I checked. Honestly, again, if the compiler wants to optimize the boxing on the grounds of optimization, so long as the language semantics are preserved, then that's fine with me. But the language semantics cannot change, not if the Java community is going to trust the ongoing enhancements to the language. Ted Neward | Principal Consultant, ThoughtWorks Java, .NET, XML Services Consulting, Teaching, Speaking, Writing http://www.thoughtworks.com | http://www.tedneward.com > -----Original Message----- > From: coin-dev-bounces at openjdk.java.net [mailto:coin-dev- > bounces at openjdk.java.net] On Behalf Of Mark Thornton > Sent: Wednesday, June 24, 2009 12:55 AM > To: Lawrence Kesteloot > Cc: coin-dev at openjdk.java.net > Subject: Re: Indexing access for Lists and Maps considered harmful? > > Lawrence Kesteloot wrote: > > Neal's argument about the ability to return an "equivalent" object is > > valid. Something has to give, that I would pick that. It's reasonable > > in nearly all cases to just return the RHS object. > > > > > If the RHS value is going to be boxed, I think it is important that it > be boxed only once and not separately for each assignment. > > Mark Thornton From brucechapman at paradise.net.nz Wed Jun 24 02:15:22 2009 From: brucechapman at paradise.net.nz (Bruce Chapman) Date: Wed, 24 Jun 2009 21:15:22 +1200 Subject: Indexing access for Lists and Maps considered harmful? In-Reply-To: <079701c9f498$7195aa50$54c0fef0$@com> References: <36c722e00906231355v28598bc7kc12280275564bec1@mail.gmail.com> <15e8b9d20906231442q4db305f4l5db912f1a651e68e@mail.gmail.com> <564879.729.qm@web112516.mail.gq1.yahoo.com> <15e8b9d20906231747y41260ea9g875ed74d721dad61@mail.gmail.com> <4A41CCA2.7010203@gmail.com> <079701c9f498$7195aa50$54c0fef0$@com> Message-ID: <4A41EEAA.7090503@paradise.net.nz> Ted Neward wrote: > In your implementation, indexSet *must* return ValueType, and it must return > the value passed in, if the existing semantics for Java are going to be > preserved. Am I missing something here? If, as I think Neal already pointed > out, we look at the expression > > a = b = c; > > The results of the intermediate expression "b = c" is "c", and therefore the > results of the expression "a = (b = c)" is "c" as well. What are we arguing > about? This is established Java language semantics, isn't it? > > JLS 15.26 says " The type of the assignment expression is the type of the variable after capture conversion " and "At run time, the result of the assignment expression is the value of the variable after the assignment has occurred." To fully retain these semantics I think there should be a set/put for the first (right hand) assignment, then a get of that value (with same index) (unless it can be proven that the get will return the set/put argument) followed by the second set/put using the result of the get. This then nicely REQUIRES any return value from the set/put to be ignored!! Note that given List list; then the type of the expression list[0] = 5 should have type Integer, not int. Where the value of an assignment expression is used, a separate get invocation nicely does the right thing. Bruce > Ted Neward | Principal Consultant, ThoughtWorks > Java, .NET, XML Services > Consulting, Teaching, Speaking, Writing > http://www.thoughtworks.com | http://www.tedneward.com > > From pbenedict at apache.org Wed Jun 24 02:25:49 2009 From: pbenedict at apache.org (Paul Benedict) Date: Wed, 24 Jun 2009 04:25:49 -0500 Subject: Indexing access for Lists and Maps considered harmful? Message-ID: I am not a fan of this proposal in general. Two things to comment on: (1) Collections are located in java.util, but the JLS can only reference classes in java.lang, correct? If I have my facts correct (doubting), this enhancement would set a new precedent by having a language feature reach into a non-lang package. (2) I don't see the benefit-to-cost ratio paying off. I wouldn't want this new language feature accepted without (a) a full working prototype and (b) a large passage of time to get through these design issues. What might make sense within 3 months of thought (coin dev's time limit) may look poorly thought out after a year's time. What comes to mind is JSR-308, JSR-305, and Neal's closures because their prototypes allow the community to weigh and play features before inclusion -- if ever whenever. When there is contention, the best solution is to prove out the idea with sweat and code. Paul From brucechapman at paradise.net.nz Wed Jun 24 02:34:09 2009 From: brucechapman at paradise.net.nz (Bruce Chapman) Date: Wed, 24 Jun 2009 21:34:09 +1200 Subject: Indexing access for Lists and Maps considered harmful? In-Reply-To: <07c001c9f4a4$cd24ba80$676e2f80$@com> References: <36c722e00906231355v28598bc7kc12280275564bec1@mail.gmail.com> <15e8b9d20906231442q4db305f4l5db912f1a651e68e@mail.gmail.com> <564879.729.qm@web112516.mail.gq1.yahoo.com> <15e8b9d20906231747y41260ea9g875ed74d721dad61@mail.gmail.com> <4A41CCA2.7010203@gmail.com> <079701c9f498$7195aa50$54c0fef0$@com> <4A41DD9D.3080909@optrak.co.uk> <07c001c9f4a4$cd24ba80$676e2f80$@com> Message-ID: <4A41F311.9090501@paradise.net.nz> Ted Neward wrote: > Under what situation would a = b = c (where b is boxed(c) ) yield different > results? Aside from concurrency scenarios, my understanding is that boxed or > not, the value is still "c", thus a would hold the value "c", boxed or > otherwise. > Digressing from a multiple assignment (its just one example of using the value of an assigment expression), but still using an assignment expression as an expression then given list list; void doSomething(int v) { .... } void doSomething(Integer v) { ...} which method is invoked by the following? doSomething(list[0]=5) If the implementation is consistent with the existing JLS, then it MUST be the second method. Bruce > From forax at univ-mlv.fr Wed Jun 24 02:57:47 2009 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Wed, 24 Jun 2009 11:57:47 +0200 Subject: Indexing access for Lists and Maps considered harmful? In-Reply-To: <15e8b9d20906232255x7d690d3csbfa454d04c2d9902@mail.gmail.com> References: <36c722e00906231355v28598bc7kc12280275564bec1@mail.gmail.com> <15e8b9d20906231442q4db305f4l5db912f1a651e68e@mail.gmail.com> <564879.729.qm@web112516.mail.gq1.yahoo.com> <15e8b9d20906231747y41260ea9g875ed74d721dad61@mail.gmail.com> <15e8b9d20906232255x7d690d3csbfa454d04c2d9902@mail.gmail.com> Message-ID: <4A41F89B.9030802@univ-mlv.fr> Neal Gafter a ?crit : [...] > My favorite solution is a combination of specification by > syntactic translation and the addition of support for extension methods. It > can be retrofitted onto any existing class or interface without breaking > backward compatibility, and can be defined to have precisely the necessary > semantics to match the JLS specification for assignment. > I think we can split the problm in two: at call site and a declaration site. At call site as you said, we need a syntactic translation to be conform with rules of the JLS about assignments. At declaration site, you want use extension methods, I'm not a big fan of them, because they don't obey to the late binding mechanism. Furthermore, I don't think kthey are needed here, a simple keyword is sufficient. Let's call it "indexer" public interface List { indexer public E get(int index); } public class MyIntList { indexer public void set(int index, int value) { ... } } There is just a small problem, coin doesn't allow new keyword ... We will need extension methods if we want closures, but we will see later. > > >> NB: I'd hereby like to repeat my suggestion to choose pragmatism over >> perfection here: >> > > > Sure, if there were a conflict between the two (there isn't) that would be > reasonable. Adding direct support for the collection interfaces to the JLS > isn't a reasonable approach either. > > Cheers, > Neal > > Cheers, R?mi From forax at univ-mlv.fr Wed Jun 24 03:04:27 2009 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Wed, 24 Jun 2009 12:04:27 +0200 Subject: Indexing access for Lists and Maps considered harmful? In-Reply-To: <4A41F311.9090501@paradise.net.nz> References: <36c722e00906231355v28598bc7kc12280275564bec1@mail.gmail.com> <15e8b9d20906231442q4db305f4l5db912f1a651e68e@mail.gmail.com> <564879.729.qm@web112516.mail.gq1.yahoo.com> <15e8b9d20906231747y41260ea9g875ed74d721dad61@mail.gmail.com> <4A41CCA2.7010203@gmail.com> <079701c9f498$7195aa50$54c0fef0$@com> <4A41DD9D.3080909@optrak.co.uk> <07c001c9f4a4$cd24ba80$676e2f80$@com> <4A41F311.9090501@paradise.net.nz> Message-ID: <4A41FA2B.80403@univ-mlv.fr> Bruce Chapman a ?crit : > Ted Neward wrote: > >> Under what situation would a = b = c (where b is boxed(c) ) yield different >> results? Aside from concurrency scenarios, my understanding is that boxed or >> not, the value is still "c", thus a would hold the value "c", boxed or >> otherwise. >> >> > Digressing from a multiple assignment (its just one example of using the > value of an assigment expression), but still using an assignment > expression as an expression then given > > list list; > > void doSomething(int v) { .... } > > void doSomething(Integer v) { ...} > > which method is invoked by the following? > > doSomething(list[0]=5) > > If the implementation is consistent with the existing JLS, then it MUST > be the second method. > > Bruce > Yes. I think you can rewrite your example as a puzzler : List list = ... void doSomething(int v) { .... } //1 void doSomething(Object o) { ...} //2 doSomething(list[0]=5) // call #2 cheers, R?mi From rssh at gradsoft.com.ua Tue Jun 23 22:01:08 2009 From: rssh at gradsoft.com.ua (Ruslan Shevchenko) Date: Wed, 24 Jun 2009 08:01:08 +0300 (EEST) Subject: Indexing access for Lists and Maps considered harmful? In-Reply-To: <4A41F89B.9030802@univ-mlv.fr> References: <36c722e00906231355v28598bc7kc12280275564bec1@mail.gmail.com> <15e8b9d20906231442q4db305f4l5db912f1a651e68e@mail.gmail.com> <564879.729.qm@web112516.mail.gq1.yahoo.com> <15e8b9d20906231747y41260ea9g875ed74d721dad61@mail.gmail.com> <15e8b9d20906232255x7d690d3csbfa454d04c2d9902@mail.gmail.com> <4A41F89B.9030802@univ-mlv.fr> Message-ID: <8bed577dba3ff494769d0294a4e65c61.squirrel@wmail.gradsoft.ua> > because they don't obey to the late binding mechanism. > Furthermore, I don't think kthey are needed here, a simple keyword is > sufficient. > Let's call it "indexer" > > public interface List { > indexer public E get(int index); > } > > public class MyIntList { > indexer public void set(int index, int value) { ... } > } > > There is just a small problem, coin doesn't allow new keyword ... > Special annotation can be used. (as in Simple Operator Overloading proposal) i.e. public class MyIntList { @Indexer public void set(int index, int value) { ... } } But I steel can't understand: why this is better then: 1. retrofit interface with names (and semantics), other then put/get indexedGetter/ingexedSetter (I prefer names #"operator:[]" and #"operator:[]=" ) and semantics for #"operator:[]=" must be return just assigned value, not previous. 2. change '=' semantics to return right part of assignment in case of assignment to indexed access. any from this solutions fix issue with compound assignment nicely. > We will need extension methods if we want closures, but > we will see later. > >> >> >>> NB: I'd hereby like to repeat my suggestion to choose pragmatism over >>> perfection here: >>> >> >> >> Sure, if there were a conflict between the two (there isn't) that would >> be >> reasonable. Adding direct support for the collection interfaces to the >> JLS >> isn't a reasonable approach either. >> >> Cheers, >> Neal >> >> > Cheers, > R?mi > > From mthornton at optrak.co.uk Wed Jun 24 03:08:37 2009 From: mthornton at optrak.co.uk (Mark Thornton) Date: Wed, 24 Jun 2009 11:08:37 +0100 Subject: Indexing access for Lists and Maps considered harmful? In-Reply-To: <8bed577dba3ff494769d0294a4e65c61.squirrel@wmail.gradsoft.ua> References: <36c722e00906231355v28598bc7kc12280275564bec1@mail.gmail.com> <15e8b9d20906231442q4db305f4l5db912f1a651e68e@mail.gmail.com> <564879.729.qm@web112516.mail.gq1.yahoo.com> <15e8b9d20906231747y41260ea9g875ed74d721dad61@mail.gmail.com> <15e8b9d20906232255x7d690d3csbfa454d04c2d9902@mail.gmail.com> <4A41F89B.9030802@univ-mlv.fr> <8bed577dba3ff494769d0294a4e65c61.squirrel@wmail.gradsoft.ua> Message-ID: <4A41FB25.2030403@optrak.co.uk> Ruslan Shevchenko wrote: > But I steel can't understand: why this is better then: > > 1. retrofit interface with names (and semantics), other then put/get > indexedGetter/ingexedSetter > > (I prefer names #"operator:[]" and #"operator:[]=" ) > > and semantics for #"operator:[]=" must be return just assigned value, > not previous. > It is very undesireable to add methods to existing interfaces. But the intent of this proposal was to allow indexed access to existing List/Map. > 2. change '=' semantics to return right part of assignment in case of > assignment to indexed access. > It is even more undesireable to change existing semantics. Nor is it desireable to have the semantics of assignment depend on whether the LHS is an index into a list or an index into an array. Mark Thornton From ted at tedneward.com Wed Jun 24 03:31:17 2009 From: ted at tedneward.com (Ted Neward) Date: Wed, 24 Jun 2009 03:31:17 -0700 Subject: Indexing access for Lists and Maps considered harmful? In-Reply-To: <4A41FA2B.80403@univ-mlv.fr> References: <36c722e00906231355v28598bc7kc12280275564bec1@mail.gmail.com> <15e8b9d20906231442q4db305f4l5db912f1a651e68e@mail.gmail.com> <564879.729.qm@web112516.mail.gq1.yahoo.com> <15e8b9d20906231747y41260ea9g875ed74d721dad61@mail.gmail.com> <4A41CCA2.7010203@gmail.com> <079701c9f498$7195aa50$54c0fef0$@com> <4A41DD9D.3080909@optrak.co.uk> <07c001c9f4a4$cd24ba80$676e2f80$@com> <4A41F311.9090501@paradise.net.nz> <4A41FA2B.80403@univ-mlv.fr> Message-ID: <07fe01c9f4b6$edef54c0$c9cdfe40$@com> This is true regardless of the map/list syntax, though, isn't it? public class BoxingPuzzler { public static void doSomething(int i) { System.out.println("int"); } public static void doSomething(Integer i) { System.out.println("Integer"); } public static void doSomething(Object o) { System.out.println("Object"); } public static void main(String[] args) { Object o = null; doSomething(o = 5); } } This prints "Object" at the command-line. (Interestingly, after a few seconds of experimentation, I can't get it to invoke the Integer version, but it definitely doesn't invoke the "int" version. Not having the Object version yields a compile error. Brighter minds than mine can probably get Integer to be invoked.) Ted Neward | Principal Consultant, ThoughtWorks Java, .NET, XML Services Consulting, Teaching, Speaking, Writing http://www.thoughtworks.com | http://www.tedneward.com > -----Original Message----- > From: R?mi Forax [mailto:forax at univ-mlv.fr] > Sent: Wednesday, June 24, 2009 3:04 AM > To: Bruce Chapman > Cc: Ted Neward; coin-dev at openjdk.java.net > Subject: Re: Indexing access for Lists and Maps considered harmful? > > Bruce Chapman a ?crit : > > Ted Neward wrote: > > > >> Under what situation would a = b = c (where b is boxed(c) ) yield > different > >> results? Aside from concurrency scenarios, my understanding is that > boxed or > >> not, the value is still "c", thus a would hold the value "c", boxed > or > >> otherwise. > >> > >> > > Digressing from a multiple assignment (its just one example of using > the > > value of an assigment expression), but still using an assignment > > expression as an expression then given > > > > list list; > > > > void doSomething(int v) { .... } > > > > void doSomething(Integer v) { ...} > > > > which method is invoked by the following? > > > > doSomething(list[0]=5) > > > > If the implementation is consistent with the existing JLS, then it > MUST > > be the second method. > > > > Bruce > > > Yes. > I think you can rewrite your example as a puzzler : > > List list = ... > void doSomething(int v) { .... } //1 > void doSomething(Object o) { ...} //2 > > doSomething(list[0]=5) // call #2 > > > cheers, > R?mi From rssh at gradsoft.com.ua Tue Jun 23 23:02:22 2009 From: rssh at gradsoft.com.ua (Ruslan Shevchenko) Date: Wed, 24 Jun 2009 09:02:22 +0300 (EEST) Subject: Indexing access for Lists and Maps considered harmful? In-Reply-To: <4A41FB25.2030403@optrak.co.uk> References: <36c722e00906231355v28598bc7kc12280275564bec1@mail.gmail.com> <15e8b9d20906231442q4db305f4l5db912f1a651e68e@mail.gmail.com> <564879.729.qm@web112516.mail.gq1.yahoo.com> <15e8b9d20906231747y41260ea9g875ed74d721dad61@mail.gmail.com> <15e8b9d20906232255x7d690d3csbfa454d04c2d9902@mail.gmail.com> <4A41F89B.9030802@univ-mlv.fr> <8bed577dba3ff494769d0294a4e65c61.squirrel@wmail.gradsoft.ua> <4A41FB25.2030403@optrak.co.uk> Message-ID: > Ruslan Shevchenko wrote: >> But I steel can't understand: why this is better then: >> >> 1. retrofit interface with names (and semantics), other then put/get >> indexedGetter/ingexedSetter >> >> (I prefer names #"operator:[]" and #"operator:[]=" ) >> >> and semantics for #"operator:[]=" must be return just assigned value, >> not previous. >> > It is very undesireable to add methods to existing interfaces. But the > intent of this proposal was to allow indexed access to existing List/Map. > i. e. without library changes ? Hmm .... [I does not think so, but this is question to authors] >> 2. change '=' semantics to return right part of assignment in case of >> assignment to indexed access. >> > It is even more undesireable to change existing semantics. Nor is it > desireable to have the semantics of assignment depend on whether the LHS > is an index into a list or an index into an array. > If we have different semantics of access methods, than we have different semantics of indexed assignments. JLS does not specify semantics of indexed access to list now. I. e. statements about indexed access will be added to JLS, possible in way, that behaviour of overall specification will look logically. Now we have two cases to do this: 1. Add statement, that index assignment will be translated to call of index-assignment method (put in maps, set in lists). [In intention of original proposal] Note, that JLS will not become inconsistent from such case: only semantics of returning value of put() looks strange, because put was not designed to participate as part in compound assignment. // that's why I think, that new method is better solution. 2. Add statement, that index assignment will be translated to call of index-assignment method, then return value will be changed to right part of assignment, boxed to type of left part, if needed. This will allow put's be part of compound assignments. Of course, this will left other things, which looks strange: (a[x]=b)==b will be not always true, //when b is primitive value and a[x] is collection of appropriative boxed object types. But note, that violation of this property also will be applied to case 1. Semantics of access statement for arrays will not changed at all. Is it possible to find variant, which will not looks (from some point fo view) strange and without library changes (?) - I don't think so. If we allow user code in compound assignments, than we allow side effects in user code, which can change result. > Mark Thornton > > From forax at univ-mlv.fr Wed Jun 24 04:04:54 2009 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Wed, 24 Jun 2009 13:04:54 +0200 Subject: Indexing access for Lists and Maps considered harmful? In-Reply-To: <07fe01c9f4b6$edef54c0$c9cdfe40$@com> References: <36c722e00906231355v28598bc7kc12280275564bec1@mail.gmail.com> <15e8b9d20906231442q4db305f4l5db912f1a651e68e@mail.gmail.com> <564879.729.qm@web112516.mail.gq1.yahoo.com> <15e8b9d20906231747y41260ea9g875ed74d721dad61@mail.gmail.com> <4A41CCA2.7010203@gmail.com> <079701c9f498$7195aa50$54c0fef0$@com> <4A41DD9D.3080909@optrak.co.uk> <07c001c9f4a4$cd24ba80$676e2f80$@com> <4A41F311.9090501@paradise.net.nz> <4A41FA2B.80403@univ-mlv.fr> <07fe01c9f4b6$edef54c0$c9cdfe40$@com> Message-ID: <4A420856.2080900@univ-mlv.fr> Ted Neward a ?crit : > This is true regardless of the map/list syntax, though, isn't it? > Yes, the compiler first try to find a method without boxing and then with boxing and with generics and boxing. This was necessary to be backward compatible with pre-boxing/pre-generics code. > public class BoxingPuzzler > { > public static void doSomething(int i) { System.out.println("int"); } > public static void doSomething(Integer i) { System.out.println("Integer"); > } > public static void doSomething(Object o) { System.out.println("Object"); } > > public static void main(String[] args) > { > Object o = null; > > doSomething(o = 5); > } > } > > This prints "Object" at the command-line. (Interestingly, after a few > seconds of experimentation, I can't get it to invoke the Integer version, > but it definitely doesn't invoke the "int" version. Not having the Object > version yields a compile error. Brighter minds than mine can probably get > Integer to be invoked.) > You can't. > Ted Neward | Principal Consultant, ThoughtWorks > Java, .NET, XML Services > Consulting, Teaching, Speaking, Writing > http://www.thoughtworks.com | http://www.tedneward.com > R?mi From rssh at gradsoft.com.ua Tue Jun 23 23:18:54 2009 From: rssh at gradsoft.com.ua (Ruslan Shevchenko) Date: Wed, 24 Jun 2009 09:18:54 +0300 (EEST) Subject: FYI: frequency of compound assigment. In-Reply-To: <07fe01c9f4b6$edef54c0$c9cdfe40$@com> References: <36c722e00906231355v28598bc7kc12280275564bec1@mail.gmail.com> <15e8b9d20906231442q4db305f4l5db912f1a651e68e@mail.gmail.com> <564879.729.qm@web112516.mail.gq1.yahoo.com> <15e8b9d20906231747y41260ea9g875ed74d721dad61@mail.gmail.com> <4A41CCA2.7010203@gmail.com> <079701c9f498$7195aa50$54c0fef0$@com> <4A41DD9D.3080909@optrak.co.uk> <07c001c9f4a4$cd24ba80$676e2f80$@com> <4A41F311.9090501@paradise.net.nz> <4A41FA2B.80403@univ-mlv.fr> <07fe01c9f4b6$edef54c0$c9cdfe40$@com> Message-ID: Hmm, small but not zero. jetty: 13 gwt-user: 20 hibernate: 2 From Thomas.Hawtin at Sun.COM Wed Jun 24 04:39:28 2009 From: Thomas.Hawtin at Sun.COM (Tom Hawtin) Date: Wed, 24 Jun 2009 12:39:28 +0100 Subject: Indexing access for Lists and Maps considered harmful? In-Reply-To: <07ba01c9f4a1$5b319d60$1194d820$@com> References: <36c722e00906231355v28598bc7kc12280275564bec1@mail.gmail.com> <15e8b9d20906231442q4db305f4l5db912f1a651e68e@mail.gmail.com> <564879.729.qm@web112516.mail.gq1.yahoo.com> <15e8b9d20906231747y41260ea9g875ed74d721dad61@mail.gmail.com> <17b2302a0906232040x4adf6894s55eab1d13e2c29a0@mail.gmail.com> <56B5CBBF-DEDA-4361-92CA-68B61AA60CEE@zwitserloot.com> <4A41DAED.6010903@optrak.co.uk> <07ba01c9f4a1$5b319d60$1194d820$@com> Message-ID: <4A421070.8030600@sun.com> Ted Neward wrote: > No. I will strongly oppose any effort to "move away from 100% consistency", > regardless of how many people on this list use a particular feature or if > it's an area that "almost nobody uses". Languages have to be consistent, or > developers' faith in that language begins to erode and the language itself > begins to die. I think the languages changes in 1.1 blew that away. Wouldn't that Java language universe be better is some of the weird conclusions of the inner class spec where simply ruled illegal? It took javac years to catch up. Getting back to this feature. Shouldn't `a[b] = c` be a drop in replacement for `a.put(b, c)`? Consider code like these: j2se/share/classes/com/sun/tools/javac/comp/Check.java: if (typeMap.put(t.tsym, t) == null) { j2se/share/classes/java/util/Collections.java: synchronized(mutex) {return m.put(key, value);} Drop in the new syntactical sugar and we have: if ((typeMap[t.tsym] = t) == null) { synchronized(mutex) {return m[key] = value;} Oops. (Admittedly a quick grep for ".put(" or ".set(" and "{" only came up with about a dozen or so of these examples in j2se.) So depending upon circumstance there is a choice of two values that the feature must return. The only winning move is not to return anything. There is no need for javac warnings and errors in these cases to be cryptic. Personally I'd lint the array pass through assignment case, but that could produce too many warnings. Tom From reinier at zwitserloot.com Wed Jun 24 07:14:49 2009 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Wed, 24 Jun 2009 16:14:49 +0200 Subject: Indexing access for Lists and Maps considered harmful? In-Reply-To: <4A421070.8030600@sun.com> References: <36c722e00906231355v28598bc7kc12280275564bec1@mail.gmail.com> <15e8b9d20906231442q4db305f4l5db912f1a651e68e@mail.gmail.com> <564879.729.qm@web112516.mail.gq1.yahoo.com> <15e8b9d20906231747y41260ea9g875ed74d721dad61@mail.gmail.com> <17b2302a0906232040x4adf6894s55eab1d13e2c29a0@mail.gmail.com> <56B5CBBF-DEDA-4361-92CA-68B61AA60CEE@zwitserloot.com> <4A41DAED.6010903@optrak.co.uk> <07ba01c9f4a1$5b319d60$1194d820$@com> <4A421070.8030600@sun.com> Message-ID: <12CA3181-9EA4-4CD6-9155-61023977C377@zwitserloot.com> On 2009/24/06, at 13:39, Tom Hawtin wrote: > The only winning move is not to return anything. > Glad to see more people are concluding this. As Tom said, the error you get when you attempt to use a[b] = c as an expression is not cryptic at all. -- Reinier Zwitserloot From neal at gafter.com Wed Jun 24 07:35:38 2009 From: neal at gafter.com (Neal Gafter) Date: Wed, 24 Jun 2009 07:35:38 -0700 Subject: Indexing access for Lists and Maps considered harmful? In-Reply-To: <4A421070.8030600@sun.com> References: <36c722e00906231355v28598bc7kc12280275564bec1@mail.gmail.com> <15e8b9d20906231442q4db305f4l5db912f1a651e68e@mail.gmail.com> <564879.729.qm@web112516.mail.gq1.yahoo.com> <15e8b9d20906231747y41260ea9g875ed74d721dad61@mail.gmail.com> <17b2302a0906232040x4adf6894s55eab1d13e2c29a0@mail.gmail.com> <56B5CBBF-DEDA-4361-92CA-68B61AA60CEE@zwitserloot.com> <4A41DAED.6010903@optrak.co.uk> <07ba01c9f4a1$5b319d60$1194d820$@com> <4A421070.8030600@sun.com> Message-ID: <15e8b9d20906240735n558cc1efgac4ab08c9152fe72@mail.gmail.com> On Wed, Jun 24, 2009 at 4:39 AM, Tom Hawtin wrote: > Getting back to this feature. Shouldn't `a[b] = c` be a drop in > replacement for `a.put(b, c)`? No, it should not. From reinier at zwitserloot.com Wed Jun 24 07:45:52 2009 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Wed, 24 Jun 2009 16:45:52 +0200 Subject: Indexing access for Lists and Maps considered harmful? In-Reply-To: <4A421070.8030600@sun.com> References: <36c722e00906231355v28598bc7kc12280275564bec1@mail.gmail.com> <15e8b9d20906231442q4db305f4l5db912f1a651e68e@mail.gmail.com> <564879.729.qm@web112516.mail.gq1.yahoo.com> <15e8b9d20906231747y41260ea9g875ed74d721dad61@mail.gmail.com> <17b2302a0906232040x4adf6894s55eab1d13e2c29a0@mail.gmail.com> <56B5CBBF-DEDA-4361-92CA-68B61AA60CEE@zwitserloot.com> <4A41DAED.6010903@optrak.co.uk> <07ba01c9f4a1$5b319d60$1194d820$@com> <4A421070.8030600@sun.com> Message-ID: I am beginning to see some concensus on this list that the neal semantics are the most preferred semantics. That is: FOO = (a[b] = c); should be equal to: a[b] = c; FOO = a[b]; and thus, both a setter and a getter call. However, I will again claim that this semantic just plain will not fit within the confines of project coin, even if you take the drastic measure of hardcoding the setter mechanic onto java.util.List. Even with drastic measures that haven't passed in coin before, such as extension methods, new keywords, or scala-esque implicit conversions, this semantic is not possible in project coin, or at least - is not going to be consistent, because of this reason: A) Expressions that are being used as statements in java are not changed - any side effects of the notion that the expression returns a value aren't eliminated just because you don't use the return value for anything. In other words, the correct semantics for: FOO = BAR; which is an expression that may be legally used as a statement, is to first calculate the value of BAR, then assign it to FOO, then calculate the value of FOO, and toss it. Fortunately, in all legal assignment statements that exist in java today, calculating the value of the LHS of an assignment is side-effect free, and therefore the compiler itself already optimizes this out, and doesn't shove FOO on the stack just to remove it again without doing anything with it. B) The only way to get to neal's semantics for SetIndex behaviour is to run a subsequent get operation immediately after the set. In other words, this: FOO = list[idx] = v; should desugar to: list.set(idx, v); FOO = list.get(idx); As so many on this list have said, this is very very important, because consistency is some sort of holy grail. So let's roll with this consistency argument, and be consistent. I thus posit that the only consistent conclusion is: C) As expressions-turned-into-statements do not stop side-effects, the expression: list[idx] = v; should desugar not to the obvious: list.set(idx, v); Because that would be inconsistent. It should desugar to: list.set(idx, v); list.get(idx); That last statement is NOT side effect free! Who knows what I stuff into my classes .get() method. It's an interface, I can do what I please! Log something, print something, start up a GUI - make a network connection - it doesn't matter. As a practical matter, running a useless get() operation is quite a performance hit, and for the few scenarios where people did write side effects into their get method, while it is technically consistent, I bet it's going to cause no end of surprises. If you step away from the consistency and technical semantics for a second, "list[idx] = v" calling the getter right after the setter is nuts. Completely unexpected. So, to put it in layman's terms: Consistency is an unattainable pipe dream - akin to appreciation for a painting, not a quantifiable measure. Please move away from it. I think putting yourself into the mind of Average Java is a far more fruitful exercise, and, if needed - quantifiable (go out, find some Joe Averages, and ask them - or just use your common sense. Puzzlers are defined as things which surprises Joe Average Joe. No single puzzler is a 'puzzler' if everyone knew chapter and verse of the JLS, and yet we all just know a thing is a puzzler when we see one) So, lets be Joe Average. Imagine he sees: void example() { Map map = new HashMap() { public Integer get(Integer key) { System.out.println("FOO!"); return super.get(key); } map.put(10, 0); callSomeOverloadedMethod(map[10] = 1); } void callSomeOverloadedMethod(Object x) { System.out..println("BAR: " + x); } void callSomeOverloadedMethod(int x) { System.out.println("BAZ:" + x); } in a code base somewhere, and think of what he'd think is going to happen. Conclusion: Any of 4 incompatible choices, at least: A) BAZ: 1 (assignment evaluates to evaluation of RHS) B) BAR: 1 (assignment evaluates to post-capture evaluation of RHS) C) FOO! BAR: 1 (assignment evaluates to LHS - e.g. call the getter) D) BAR: 0 (assignment desugars to map.put(), which returns the value that previously occupied the slot of the key) We can talk about what's the most consistent choice till the cows come home, and we can even pick a winner (which so happens to appear to be the most complicated one, which is C - just to make things worse), but in the end Joe Average Java just is so not going to get that. The only winning answer is not to choose at all, and return void. That way, 25% of the people who get it right are inconvenienced all of the 20 times it's seen usage in a multi-man-year project, and the remaning 75% don't spend an hour or two chasing down why it doesn't work. I take it as a given that if you fail to guess the right semantic for 'list[a] = b', that the result bug is NOT all that obvious, and certainly does not clearly tell you right as you write/compile your code. It'll eventually show up as a runtime issue, probably not even an exception, just errant behaviour in your program. No stack trace to help you, the problem appearing miles away in both time and distance from the offending code line. In other words, in a bad scenario, many many hours worth of bug hunting. And all for this trouble for Joe Average just because we're all chasing the mythical 'consistency' white whale that is clearly in the eye of the beholder, and not a quantifiable entity. --Reinier Zwitserloot From mthornton at optrak.co.uk Wed Jun 24 08:01:24 2009 From: mthornton at optrak.co.uk (Mark Thornton) Date: Wed, 24 Jun 2009 16:01:24 +0100 Subject: Indexing access for Lists and Maps considered harmful? In-Reply-To: References: <36c722e00906231355v28598bc7kc12280275564bec1@mail.gmail.com> <15e8b9d20906231442q4db305f4l5db912f1a651e68e@mail.gmail.com> <564879.729.qm@web112516.mail.gq1.yahoo.com> <15e8b9d20906231747y41260ea9g875ed74d721dad61@mail.gmail.com> <17b2302a0906232040x4adf6894s55eab1d13e2c29a0@mail.gmail.com> <56B5CBBF-DEDA-4361-92CA-68B61AA60CEE@zwitserloot.com> <4A41DAED.6010903@optrak.co.uk> <07ba01c9f4a1$5b319d60$1194d820$@com> <4A421070.8030600@sun.com> Message-ID: <4A423FC4.8090200@optrak.co.uk> Reinier Zwitserloot wrote: > B) BAR: 1 (assignment evaluates to post-capture evaluation of RHS) > > While the current wording in the JLS appears to be incompatible with this, does not this description also accurately describe the current behaviour with arrays (or any other currently permitted LHS)? Mark Thornton From abies at adres.pl Wed Jun 24 08:04:56 2009 From: abies at adres.pl (abies at adres.pl) Date: Wed, 24 Jun 2009 17:04:56 +0200 Subject: Indexing access for Lists and Maps considered harmful? In-Reply-To: E698DE73-BF8D-4ED9-A8BF-4227B54B1A4D@zwitserloot.com Message-ID: "Reinier Zwitserloot" napisa?(a): > I am beginning to see some concensus on this list that the neal > semantics are the most preferred semantics. That is: > > FOO = (a[b] = c); > > should be equal to: > > a[b] = c; > FOO = a[b]; > > and thus, both a setter and a getter call. I still don't understand why. It is not a case with current assignment operator. public class Test { volatile static int[] arr = new int[1]; volatile static int val = 0; public static void main(String[] args) { int x,y; x = (val = 3); y = (arr[0] = 5); } } compiles into public static void main(java.lang.String[]); Code: 0: iconst_3 1: dup 2: putstatic #2; //Field val:I 5: istore_1 6: getstatic #3; //Field arr:[I 9: iconst_0 10: iconst_5 11: dup_x2 12: iastore 13: istore_2 14: return Please note that there is no get from the arr nor from val, even if both are volatile and could be possible written into by another thread concurrently. x = (y = z) IS NOT EQUAL TO y = z; x = y; in current java. It is equal to tmp = z; y = tmp; x = tmp; I don't understand why suddenly for sugar-on-top-of-collections we have to change the rules which are valid for normal values and arrays. There is no 'getter' equivalent called for anything in java currently, if you will modify jvm to catch retrieve-value-from-array, it will not be invoked, so why should getter be called on collections? Regards, Artur Biesiadowski From neal at gafter.com Wed Jun 24 08:12:08 2009 From: neal at gafter.com (Neal Gafter) Date: Wed, 24 Jun 2009 08:12:08 -0700 Subject: Indexing access for Lists and Maps considered harmful? In-Reply-To: References: <36c722e00906231355v28598bc7kc12280275564bec1@mail.gmail.com> <564879.729.qm@web112516.mail.gq1.yahoo.com> <15e8b9d20906231747y41260ea9g875ed74d721dad61@mail.gmail.com> <17b2302a0906232040x4adf6894s55eab1d13e2c29a0@mail.gmail.com> <56B5CBBF-DEDA-4361-92CA-68B61AA60CEE@zwitserloot.com> <4A41DAED.6010903@optrak.co.uk> <07ba01c9f4a1$5b319d60$1194d820$@com> <4A421070.8030600@sun.com> Message-ID: <15e8b9d20906240812j40ad9ce4y14492e57a3f364f1@mail.gmail.com> On Wed, Jun 24, 2009 at 7:45 AM, Reinier Zwitserloot < reinier at zwitserloot.com> wrote: > I am beginning to see some concensus on this list that the neal > semantics are the most preferred semantics. That is: > > FOO = (a[b] = c); > > should be equal to: > > a[b] = c; > FOO = a[b]; > > and thus, both a setter and a getter call. I wasn't suggesting that a get operation is required. I was suggesting that the specification for the indexing operator must allow the API to provide the result value of the assignment. Calling the getter is one (as you've discovered, poor) way to accomplish that. > So, to put it in layman's terms: Consistency is an unattainable pipe > dream - akin to appreciation for a painting, not a quantifiable > measure. I think you've demonstrated that you don't know how to achieve it. That's not the same as being unattainable. Here's another way that doesn't require extension methods: define a[i] (where a is not an array type) in an rvalue context by translation as operator_index_get(a, i) and a[i] = value by translation as operator_index_put(a, i, value) Modulo details about compound operators, some more precision, and API design advice, that's the gist of the specification. If you want to use the index operators with collections, you'd typically import these methods from a utility class: import static java.util.Collections.operator_index_get; import static java.util.Collections.operator_index_put; and the implementation in Collections would behave as required: public static E operator_index_put(List list, int index, E value) { list.set(index, value); return value; } public static V operator_index_put(Map map, K key, V value) { map.put(key, value); return value; } Short, sweet, and satisfies all the requirements. Not my favorite solution for this problem space, but better than most of the others that have been proposed. From jjb at google.com Wed Jun 24 08:14:46 2009 From: jjb at google.com (Joshua Bloch) Date: Wed, 24 Jun 2009 08:14:46 -0700 Subject: Indexing access for Lists and Maps considered harmful? In-Reply-To: References: Message-ID: <17b2302a0906240814i7d930e35nc8f4a0a1d0aa7ba2@mail.gmail.com> I'm with Artur on this. I think we're making a mountain out of a molehill. The fact that collection.put(value) is an implementation detail. The value of (a = expr) is and should remain expr. Josh 2009/6/24 > > > "Reinier Zwitserloot" napisa?(a): > > I am beginning to see some concensus on this list that the neal > > semantics are the most preferred semantics. That is: > > > > FOO = (a[b] = c); > > > > should be equal to: > > > > a[b] = c; > > FOO = a[b]; > > > > and thus, both a setter and a getter call. > > > I still don't understand why. It is not a case with current assignment > operator. > public class Test { > volatile static int[] arr = new int[1]; > volatile static int val = 0; > public static void main(String[] args) { > int x,y; > x = (val = 3); > y = (arr[0] = 5); > } > } > > > compiles into > > public static void main(java.lang.String[]); > Code: > 0: iconst_3 > 1: dup > 2: putstatic #2; //Field val:I > 5: istore_1 > 6: getstatic #3; //Field arr:[I > 9: iconst_0 > 10: iconst_5 > 11: dup_x2 > 12: iastore > 13: istore_2 > 14: return > > > Please note that there is no get from the arr nor from val, even if both > are volatile and could be possible written into by another thread > concurrently. > > x = (y = z) > > IS NOT EQUAL TO > > y = z; > x = y; > > in current java. > > It is equal to > > tmp = z; > y = tmp; > x = tmp; > > I don't understand why suddenly for sugar-on-top-of-collections we have to > change the rules which are valid for normal values and arrays. There is no > 'getter' equivalent called for anything in java currently, if you will > modify jvm to catch retrieve-value-from-array, it will not be invoked, so > why should getter be called on collections? > > Regards, > Artur Biesiadowski > > From forax at univ-mlv.fr Wed Jun 24 08:35:45 2009 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Wed, 24 Jun 2009 17:35:45 +0200 Subject: Indexing access for Lists and Maps considered harmful? In-Reply-To: <15e8b9d20906240812j40ad9ce4y14492e57a3f364f1@mail.gmail.com> References: <36c722e00906231355v28598bc7kc12280275564bec1@mail.gmail.com> <564879.729.qm@web112516.mail.gq1.yahoo.com> <15e8b9d20906231747y41260ea9g875ed74d721dad61@mail.gmail.com> <17b2302a0906232040x4adf6894s55eab1d13e2c29a0@mail.gmail.com> <56B5CBBF-DEDA-4361-92CA-68B61AA60CEE@zwitserloot.com> <4A41DAED.6010903@optrak.co.uk> <07ba01c9f4a1$5b319d60$1194d820$@com> <4A421070.8030600@sun.com> <15e8b9d20906240812j40ad9ce4y14492e57a3f364f1@mail.gmail.com> Message-ID: <4A4247D1.70009@univ-mlv.fr> Neal Gafter a ?crit : > On Wed, Jun 24, 2009 at 7:45 AM, Reinier Zwitserloot < > reinier at zwitserloot.com> wrote: > > >> I am beginning to see some concensus on this list that the neal >> semantics are the most preferred semantics. That is: >> >> FOO = (a[b] = c); >> >> should be equal to: >> >> a[b] = c; >> FOO = a[b]; >> >> and thus, both a setter and a getter call. >> > > > I wasn't suggesting that a get operation is required. I was suggesting that > the specification for the indexing operator must allow the API to provide > the result value of the assignment. Calling the getter is one (as you've > discovered, poor) way to accomplish that. > > > >> So, to put it in layman's terms: Consistency is an unattainable pipe >> dream - akin to appreciation for a painting, not a quantifiable >> measure. >> > > > I think you've demonstrated that you don't know how to achieve it. That's > not the same as being unattainable. Here's another way that doesn't require > extension methods: > > define a[i] (where a is not an array type) in an rvalue context by > translation as > > operator_index_get(a, i) > > and a[i] = value by translation as > > operator_index_put(a, i, value) > > Modulo details about compound operators, some more precision, and API design > advice, that's the gist of the specification. If you want to use the index > operators with collections, you'd typically import these methods from a > utility class: > > import static java.util.Collections.operator_index_get; > import static java.util.Collections.operator_index_put; > > and the implementation in Collections would behave as required: > > public static E operator_index_put(List list, int index, E value) { > list.set(index, value); > return value; > } > public static V operator_index_put(Map map, K key, V value) { > map.put(key, value); > return value; > } > > Short, sweet, and satisfies all the requirements. Not my favorite solution > for this problem space, but better than most of the others that have been > proposed. > > import static put symbol name is the scope, do you propose that the compiler look for any "operator_index_get" in the scope ? import static java.util.Collections.operator_index_get; class A { List list; public int operator_index_get(Object o, int index) { ... return list[index]; } } How this example is translated by the compiler ? Morever with extension methods is that you loose the polymorphism : public static E operator_index_get(Collection list, int index) { Iterator it = list.iterator(); for(int i=0; i < index; i++) it.next(); return it.next(); } public static E operator_index_get(List list, int index) { return list.get(index, value); } ... Collection c = new ArrayList(); System.out.println(printlnc[3]); // use operator_index_get(Collection ...) Java is still a OO language, isn't it ? R?mi From neal at gafter.com Wed Jun 24 09:32:28 2009 From: neal at gafter.com (Neal Gafter) Date: Wed, 24 Jun 2009 09:32:28 -0700 Subject: Indexing access for Lists and Maps considered harmful? In-Reply-To: <4A4247D1.70009@univ-mlv.fr> References: <36c722e00906231355v28598bc7kc12280275564bec1@mail.gmail.com> <17b2302a0906232040x4adf6894s55eab1d13e2c29a0@mail.gmail.com> <56B5CBBF-DEDA-4361-92CA-68B61AA60CEE@zwitserloot.com> <4A41DAED.6010903@optrak.co.uk> <07ba01c9f4a1$5b319d60$1194d820$@com> <4A421070.8030600@sun.com> <15e8b9d20906240812j40ad9ce4y14492e57a3f364f1@mail.gmail.com> <4A4247D1.70009@univ-mlv.fr> Message-ID: <15e8b9d20906240932m72a2748cyb683d1df0208fd08@mail.gmail.com> On Wed, Jun 24, 2009 at 8:35 AM, R?mi Forax wrote: > import static put symbol name is the scope, do you propose that the > compiler look for > any "operator_index_get" in the scope ? As I said, this is not my preferred solution to this problem space, but if you take this approach, then yes. import static java.util.Collections.operator_index_get; > > class A { > List list; > > public int operator_index_get(Object o, int index) { > ... > return list[index]; > } > } > > How this example is translated by the compiler ? The same way it translates any self-recursive method. Do you think it likely that someone would accidentally write a method like that? FindBugs will point out this problem. This is one of the reasons I prefer an approach based on extension methods. Morever with extension methods is that you loose the polymorphism : I think you mean that the spec depends on ad-hoc polymorphism (overloading) rather than subtype polymorphism (overriding). The actual implementation of the operators, as I've shown, do indeed depend on subtype polymorphism in precisely the same way as the original proposal. The original proposal simply cannot be retrofitted onto the interface Collection at all, and you've shown that this proposal could (though your choice of implementation is problematic). Just because you could doesn't mean you should. Looking at it another way: this alternative encodes the meaning of the index operators in external APIs, instead of hardcoding them in the (external) JLS. APIs can be overloaded, and can be defined in terms of methods that may be overridden. The JLS cannot be "overloaded" or "overridden" at all. From abies at adres.pl Wed Jun 24 10:14:19 2009 From: abies at adres.pl (Artur Biesiadowski) Date: Wed, 24 Jun 2009 19:14:19 +0200 Subject: Indexing access for Lists and Maps considered harmful? In-Reply-To: References: Message-ID: <4A425EEB.7010401@adres.pl> Paul Benedict wrote: > I am not a fan of this proposal in general. Two things to comment on: > > (1) Collections are located in java.util, but the JLS can only > reference classes in java.lang, correct? If I have my facts correct > (doubting), this enhancement would set a new precedent by having a > language feature reach into a non-lang package. > Look at java.lang.Iterable. It was added to implement forach operator and by that JLS indirectly references java.util.Iterator. I think that in each proposal, there are just few new interfaces added in java.lang for facilitating [] access. java.util classes will implement those classes, but don't have to mentioned in JLS. So, [] access is not breaking the java.lang boundaries, unlike already existing foreach. Regards, Artur Biesiadowski From jjb at google.com Wed Jun 24 10:22:41 2009 From: jjb at google.com (Joshua Bloch) Date: Wed, 24 Jun 2009 10:22:41 -0700 Subject: Indexing access for Lists and Maps considered harmful? In-Reply-To: <17b2302a0906240814i7d930e35nc8f4a0a1d0aa7ba2@mail.gmail.com> References: <17b2302a0906240814i7d930e35nc8f4a0a1d0aa7ba2@mail.gmail.com> Message-ID: <17b2302a0906241022n532057bq2b3efb7d62f611f6@mail.gmail.com> P.S. I typed this in a hurry. What I meant to say is "The fact that Map.put (and List.set) returns a value is an implementation detail (with respect to the endeavor at hand). Sorry for the confusion, Josh 2009/6/24 Joshua Bloch > I'm with Artur on this. I think we're making a mountain out of a molehill. > The fact that collection.put(value) is an implementation detail. The > value of (a = expr) is and should remain expr. > Josh > > 2009/6/24 > > >> >> "Reinier Zwitserloot" napisa?(a): >> > I am beginning to see some concensus on this list that the neal >> > semantics are the most preferred semantics. That is: >> > >> > FOO = (a[b] = c); >> > >> > should be equal to: >> > >> > a[b] = c; >> > FOO = a[b]; >> > >> > and thus, both a setter and a getter call. >> >> >> I still don't understand why. It is not a case with current assignment >> operator. >> public class Test { >> volatile static int[] arr = new int[1]; >> volatile static int val = 0; >> public static void main(String[] args) { >> int x,y; >> x = (val = 3); >> y = (arr[0] = 5); >> } >> } >> >> >> compiles into >> >> public static void main(java.lang.String[]); >> Code: >> 0: iconst_3 >> 1: dup >> 2: putstatic #2; //Field val:I >> 5: istore_1 >> 6: getstatic #3; //Field arr:[I >> 9: iconst_0 >> 10: iconst_5 >> 11: dup_x2 >> 12: iastore >> 13: istore_2 >> 14: return >> >> >> Please note that there is no get from the arr nor from val, even if both >> are volatile and could be possible written into by another thread >> concurrently. >> >> x = (y = z) >> >> IS NOT EQUAL TO >> >> y = z; >> x = y; >> >> in current java. >> >> It is equal to >> >> tmp = z; >> y = tmp; >> x = tmp; >> >> I don't understand why suddenly for sugar-on-top-of-collections we have to >> change the rules which are valid for normal values and arrays. There is no >> 'getter' equivalent called for anything in java currently, if you will >> modify jvm to catch retrieve-value-from-array, it will not be invoked, so >> why should getter be called on collections? >> >> Regards, >> Artur Biesiadowski >> >> > From reinier at zwitserloot.com Wed Jun 24 12:25:38 2009 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Wed, 24 Jun 2009 21:25:38 +0200 Subject: Indexing access for Lists and Maps considered harmful? In-Reply-To: <17b2302a0906241022n532057bq2b3efb7d62f611f6@mail.gmail.com> References: <17b2302a0906240814i7d930e35nc8f4a0a1d0aa7ba2@mail.gmail.com> <17b2302a0906241022n532057bq2b3efb7d62f611f6@mail.gmail.com> Message-ID: <346B7232-6223-468F-ABA2-6A08E7B6C267@zwitserloot.com> Neal, your conclusion that, instead of combining a set/put and a get call, we need a new interface / desugaring to a method you then statically import / extension method in / etc - which has a single call that takes in a value, and returns the post-conversion representation of that value, cannot be reconciled with java.util.List, nor with java.util.Map, without breaking backwards compatibility. Therefore, any movement in that direction would result in non-standard Map and List implementations not supporting the syntax, until someone updates them. Talk about inconsistency. I'd much rather have SetIndex and GetIndex interfaces that can be retrofitted on top of List and Map without breaking existing code. If this means a[i] = x is a statement and not an expression when it desugars into SetIndex/GetIndex, so be it. NB: I've said my piece, so I'll let others come up with an actual workable proposal. I don't really give a hoot about this proposal in the first place, as I use List.get(idx) and List.set(idx, v) pretty much never, and I can live with writing it longhand for maps. I'd rate map and list literals, especially literals that can easily be made immutable (or better: immutable by default - if you want mutable, stuff an immutable literal in an ArrayList/HashMap constructor), as seeing on the order of 100x more use at least in my code base than this stuff. -- Reinier Zwitserloot From neal at gafter.com Wed Jun 24 12:37:04 2009 From: neal at gafter.com (Neal Gafter) Date: Wed, 24 Jun 2009 12:37:04 -0700 Subject: Indexing access for Lists and Maps considered harmful? In-Reply-To: <346B7232-6223-468F-ABA2-6A08E7B6C267@zwitserloot.com> References: <17b2302a0906240814i7d930e35nc8f4a0a1d0aa7ba2@mail.gmail.com> <17b2302a0906241022n532057bq2b3efb7d62f611f6@mail.gmail.com> <346B7232-6223-468F-ABA2-6A08E7B6C267@zwitserloot.com> Message-ID: <15e8b9d20906241237j6e029897k14c774436e6328bb@mail.gmail.com> On Wed, Jun 24, 2009 at 12:25 PM, Reinier Zwitserloot < reinier at zwitserloot.com> wrote: > Neal, your conclusion that, instead of combining a set/put and a get call, > we need a new interface / desugaring to a method you then statically import > / extension method in / etc - which has a single call that takes in a value, > and returns the post-conversion representation of that value, cannot be > reconciled with java.util.List, nor with java.util.Map, without breaking > backwards compatibility. I've already shown how to retrofit that solution to List and Map without breaking backward compatibility. From reinier at zwitserloot.com Wed Jun 24 13:02:18 2009 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Wed, 24 Jun 2009 22:02:18 +0200 Subject: Indexing access for Lists and Maps considered harmful? In-Reply-To: <15e8b9d20906241237j6e029897k14c774436e6328bb@mail.gmail.com> References: <17b2302a0906240814i7d930e35nc8f4a0a1d0aa7ba2@mail.gmail.com> <17b2302a0906241022n532057bq2b3efb7d62f611f6@mail.gmail.com> <346B7232-6223-468F-ABA2-6A08E7B6C267@zwitserloot.com> <15e8b9d20906241237j6e029897k14c774436e6328bb@mail.gmail.com> Message-ID: <9D579E3F-C155-4751-BFAB-662883ECC17E@zwitserloot.com> That isn't a retrofit; existing implementations simply do not work unless you statically import a newly written method. trying to write a generic form of such a method would have to build it from the put and get primitives, which puts you in the same boat: needless and expected get calls in 99% of all assignments. So, no, you haven't shown this. --Reinier Zwitserloot On 2009/24/06, at 21:37, Neal Gafter wrote: > On Wed, Jun 24, 2009 at 12:25 PM, Reinier Zwitserloot > wrote: > Neal, your conclusion that, instead of combining a set/put and a get > call, we need a new interface / desugaring to a method you then > statically import / extension method in / etc - which has a single > call that takes in a value, and returns the post-conversion > representation of that value, cannot be reconciled with > java.util.List, nor with java.util.Map, without breaking backwards > compatibility. > > I've already shown how to retrofit that solution to List and Map > without breaking backward compatibility. From neal at gafter.com Wed Jun 24 13:08:27 2009 From: neal at gafter.com (Neal Gafter) Date: Wed, 24 Jun 2009 13:08:27 -0700 Subject: Indexing access for Lists and Maps considered harmful? In-Reply-To: <9D579E3F-C155-4751-BFAB-662883ECC17E@zwitserloot.com> References: <17b2302a0906240814i7d930e35nc8f4a0a1d0aa7ba2@mail.gmail.com> <17b2302a0906241022n532057bq2b3efb7d62f611f6@mail.gmail.com> <346B7232-6223-468F-ABA2-6A08E7B6C267@zwitserloot.com> <15e8b9d20906241237j6e029897k14c774436e6328bb@mail.gmail.com> <9D579E3F-C155-4751-BFAB-662883ECC17E@zwitserloot.com> Message-ID: <15e8b9d20906241308m42e24c13q4f8332768d89fac0@mail.gmail.com> On Wed, Jun 24, 2009 at 1:02 PM, Reinier Zwitserloot < reinier at zwitserloot.com> wrote: > That isn't a retrofit; existing implementations simply do not work unless > you statically import a newly written method. > Exactly: programmers opt-in to this form. > trying to write a generic form of such a method would have to build it from > the put and get primitives, which puts you in the same boat: needless and > expected get calls in 99% of all assignments. So, no, you haven't shown > this. > I don't see a needless get call in the implementation I provided. Do you? From rssh at gradsoft.com.ua Wed Jun 24 08:37:46 2009 From: rssh at gradsoft.com.ua (Ruslan Shevchenko) Date: Wed, 24 Jun 2009 18:37:46 +0300 (EEST) Subject: Indexing access for Lists and Maps considered harmful? In-Reply-To: <15e8b9d20906241308m42e24c13q4f8332768d89fac0@mail.gmail.com> References: <17b2302a0906240814i7d930e35nc8f4a0a1d0aa7ba2@mail.gmail.com> <17b2302a0906241022n532057bq2b3efb7d62f611f6@mail.gmail.com> <346B7232-6223-468F-ABA2-6A08E7B6C267@zwitserloot.com> <15e8b9d20906241237j6e029897k14c774436e6328bb@mail.gmail.com> <9D579E3F-C155-4751-BFAB-662883ECC17E@zwitserloot.com> <15e8b9d20906241308m42e24c13q4f8332768d89fac0@mail.gmail.com> Message-ID: > On Wed, Jun 24, 2009 at 1:02 PM, Reinier Zwitserloot < > reinier at zwitserloot.com> wrote: > >> That isn't a retrofit; existing implementations simply do not work >> unless >> you statically import a newly written method. >> > > Exactly: programmers opt-in to this form. > Or compiler can use Collections.operator_set_index(), when desugaring operator[] in compound assignment, where first operator is index over List or Map. (It is possible to look on this as 'extension methods at compile-time'). (it's variant #6, which can be practically usable). > >> trying to write a generic form of such a method would have to build it >> from >> the put and get primitives, which puts you in the same boat: needless >> and >> expected get calls in 99% of all assignments. So, no, you haven't shown >> this. >> > > I don't see a needless get call in the implementation I provided. Do you? > > From reinier at zwitserloot.com Wed Jun 24 14:21:36 2009 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Wed, 24 Jun 2009 23:21:36 +0200 Subject: Indexing access for Lists and Maps considered harmful? In-Reply-To: <15e8b9d20906241308m42e24c13q4f8332768d89fac0@mail.gmail.com> References: <17b2302a0906240814i7d930e35nc8f4a0a1d0aa7ba2@mail.gmail.com> <17b2302a0906241022n532057bq2b3efb7d62f611f6@mail.gmail.com> <346B7232-6223-468F-ABA2-6A08E7B6C267@zwitserloot.com> <15e8b9d20906241237j6e029897k14c774436e6328bb@mail.gmail.com> <9D579E3F-C155-4751-BFAB-662883ECC17E@zwitserloot.com> <15e8b9d20906241308m42e24c13q4f8332768d89fac0@mail.gmail.com> Message-ID: Which part of "Trying to write a GENERIC FORM OF SUCH A METHOD" was confusing to you, neal? Perhaps 'generic'. I meant: That can add [] support to *any* java.util.List or java.util.Map. --Reinier Zwitserloot On 2009/24/06, at 22:08, Neal Gafter wrote: > On Wed, Jun 24, 2009 at 1:02 PM, Reinier Zwitserloot > wrote: > That isn't a retrofit; existing implementations simply do not work > unless you statically import a newly written method. > > Exactly: programmers opt-in to this form. > > trying to write a generic form of such a method would have to build > it from the put and get primitives, which puts you in the same boat: > needless and expected get calls in 99% of all assignments. So, no, > you haven't shown this. > > I don't see a needless get call in the implementation I provided. > Do you? From r.spilker at gmail.com Wed Jun 24 14:26:31 2009 From: r.spilker at gmail.com (Roel Spilker) Date: Wed, 24 Jun 2009 23:26:31 +0200 Subject: Indexing access for Lists and Maps considered harmful? In-Reply-To: <17b2302a0906240814i7d930e35nc8f4a0a1d0aa7ba2@mail.gmail.com> References: <17b2302a0906240814i7d930e35nc8f4a0a1d0aa7ba2@mail.gmail.com> Message-ID: The following code and compiler output suggest that the value of (a = expr) not expr is. class Foo { public static void main() { int x, expr; long a; x = (a = expr); } } Foo.java:5: possible loss of precision found : long required: int x = (a = expr); ^ 1 error 2009/6/24 Joshua Bloch > I'm with Artur on this. I think we're making a mountain out of a molehill. > The fact that collection.put(value) is an implementation detail. The > value of (a = expr) is and should remain expr. > Josh > From jjb at google.com Wed Jun 24 14:34:03 2009 From: jjb at google.com (Joshua Bloch) Date: Wed, 24 Jun 2009 14:34:03 -0700 Subject: Indexing access for Lists and Maps considered harmful? In-Reply-To: References: <17b2302a0906240814i7d930e35nc8f4a0a1d0aa7ba2@mail.gmail.com> Message-ID: <17b2302a0906241434h54d60ecdh8a315b3a5baa3b30@mail.gmail.com> Roel, You're right. What I said was an approximation to the truth. My bad. But the point remains. Josh On Wed, Jun 24, 2009 at 2:26 PM, Roel Spilker wrote: > The following code and compiler output suggest that the value of (a = expr) not expr is. > > class Foo { > public static void main() { > int x, expr; > long a; > x = (a = expr); > > } > } > > Foo.java:5: possible loss of precision > found : long > required: int > x = (a = expr); > ^ > 1 error > > > > 2009/6/24 Joshua Bloch > >> I'm with Artur on this. I think we're making a mountain out of a >> molehill. >> The fact that collection.put(value) is an implementation detail. The >> value of (a = expr) is and should remain expr. >> Josh >> > From r.spilker at gmail.com Wed Jun 24 15:14:21 2009 From: r.spilker at gmail.com (Roel Spilker) Date: Thu, 25 Jun 2009 00:14:21 +0200 Subject: Indexing access for Lists and Maps considered harmful? In-Reply-To: <17b2302a0906241434h54d60ecdh8a315b3a5baa3b30@mail.gmail.com> References: <17b2302a0906240814i7d930e35nc8f4a0a1d0aa7ba2@mail.gmail.com> <17b2302a0906241434h54d60ecdh8a315b3a5baa3b30@mail.gmail.com> Message-ID: For as far as I'm concerned, for Java7 we could start with just defining the [] access and assign operators to work on java.util.List and java.util.Map for now. It is not unprecedented to have specific operator overloading to special classes, like the + for java.lang.String. Allowing operator overloading in libraries, as people on this list suggest, is, if I understand correctly, too big for project coin :-) And yes, List and Map are not in java.lang. Is that really a problem? From neal at gafter.com Wed Jun 24 15:45:25 2009 From: neal at gafter.com (Neal Gafter) Date: Wed, 24 Jun 2009 15:45:25 -0700 Subject: Indexing access for Lists and Maps considered harmful? In-Reply-To: References: <17b2302a0906240814i7d930e35nc8f4a0a1d0aa7ba2@mail.gmail.com> <17b2302a0906241022n532057bq2b3efb7d62f611f6@mail.gmail.com> <346B7232-6223-468F-ABA2-6A08E7B6C267@zwitserloot.com> <15e8b9d20906241237j6e029897k14c774436e6328bb@mail.gmail.com> <9D579E3F-C155-4751-BFAB-662883ECC17E@zwitserloot.com> <15e8b9d20906241308m42e24c13q4f8332768d89fac0@mail.gmail.com> Message-ID: <15e8b9d20906241545v52028b5bjc852488c16392b50@mail.gmail.com> On Wed, Jun 24, 2009 at 2:21 PM, Reinier Zwitserloot < reinier at zwitserloot.com> wrote: > Which part of "Trying to write a GENERIC FORM OF SUCH A METHOD" was > confusing to you, neal? Perhaps 'generic'. I meant: That can add [] support > to *any* java.util.List or java.util.Map. > That's precisely what I gave the code for. I showed the implementation of the GENERIC index-assignment methods for *all* List and Maps. Would you like to see the two one-line index-get methods too? From Joe.Darcy at Sun.COM Wed Jun 24 17:00:19 2009 From: Joe.Darcy at Sun.COM (Joe Darcy) Date: Wed, 24 Jun 2009 17:00:19 -0700 Subject: Indexing access for Lists and Maps: Don't Panic! Message-ID: <4A42BE13.7000604@sun.com> Hello. A meta-comment on the voluminous email traffic about the potentially puzzling semantics of the proposed setting indexing operators for Lists and Maps: Don't Panic! Such issues being uncovered, analyzed, and subsequently fixed is an expected part of language evolution. In my estimation, this is a relatively minor problem that can be addressed in subsequent revisions of the indexing proposal. -Joe From reinier at zwitserloot.com Wed Jun 24 18:41:29 2009 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Thu, 25 Jun 2009 03:41:29 +0200 Subject: Indexing access for Lists and Maps considered harmful? In-Reply-To: <15e8b9d20906241308m42e24c13q4f8332768d89fac0@mail.gmail.com> References: <17b2302a0906240814i7d930e35nc8f4a0a1d0aa7ba2@mail.gmail.com> <17b2302a0906241022n532057bq2b3efb7d62f611f6@mail.gmail.com> <346B7232-6223-468F-ABA2-6A08E7B6C267@zwitserloot.com> <15e8b9d20906241237j6e029897k14c774436e6328bb@mail.gmail.com> <9D579E3F-C155-4751-BFAB-662883ECC17E@zwitserloot.com> <15e8b9d20906241308m42e24c13q4f8332768d89fac0@mail.gmail.com> Message-ID: <994527FE-B2CC-4596-BBF5-CA03DD7B58CF@zwitserloot.com> Your general solution does not follow the suggested semantic of returning effectively the same value that ends up in the map/list. For example, a map that turns any null reference into a marker object would pass-through 'null' and not 'MARKER'. It is therefore not a consistent solution. To make your solution fit the bill for any Map or List, the wrapper method needs to invoke get(), which isn't acceptable for previously stated reasons. --Reinier Zwitserloot On 2009/24/06, at 22:08, Neal Gafter wrote: > On Wed, Jun 24, 2009 at 1:02 PM, Reinier Zwitserloot > wrote: > That isn't a retrofit; existing implementations simply do not work > unless you statically import a newly written method. > > Exactly: programmers opt-in to this form. > > trying to write a generic form of such a method would have to build > it from the put and get primitives, which puts you in the same boat: > needless and expected get calls in 99% of all assignments. So, no, > you haven't shown this. > > I don't see a needless get call in the implementation I provided. > Do you? From reinier at zwitserloot.com Wed Jun 24 18:43:49 2009 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Thu, 25 Jun 2009 03:43:49 +0200 Subject: Indexing access for Lists and Maps: Don't Panic! In-Reply-To: <4A42BE13.7000604@sun.com> References: <4A42BE13.7000604@sun.com> Message-ID: <1057BEB2-7B58-4F03-8231-96558B4FC9C4@zwitserloot.com> If this list can't figure it out, it seems somewhat presumptuous to think that your average java programmer will. As this coin proposal is purely boilerplate removal, we should take care not to make the boilerplate form more confusing than the original, lest we miss the aim of this project entirely. --Reinier Zwitserloot On 2009/25/06, at 02:00, Joe Darcy wrote: > Hello. > > A meta-comment on the voluminous email traffic about the potentially > puzzling semantics of the proposed setting indexing operators for > Lists > and Maps: Don't Panic! > > Such issues being uncovered, analyzed, and subsequently fixed is an > expected part of language evolution. In my estimation, this is a > relatively minor problem that can be addressed in subsequent revisions > of the indexing proposal. > > -Joe > From neal at gafter.com Wed Jun 24 19:23:32 2009 From: neal at gafter.com (Neal Gafter) Date: Wed, 24 Jun 2009 19:23:32 -0700 Subject: Indexing access for Lists and Maps considered harmful? In-Reply-To: <994527FE-B2CC-4596-BBF5-CA03DD7B58CF@zwitserloot.com> References: <17b2302a0906240814i7d930e35nc8f4a0a1d0aa7ba2@mail.gmail.com> <17b2302a0906241022n532057bq2b3efb7d62f611f6@mail.gmail.com> <346B7232-6223-468F-ABA2-6A08E7B6C267@zwitserloot.com> <15e8b9d20906241237j6e029897k14c774436e6328bb@mail.gmail.com> <9D579E3F-C155-4751-BFAB-662883ECC17E@zwitserloot.com> <15e8b9d20906241308m42e24c13q4f8332768d89fac0@mail.gmail.com> <994527FE-B2CC-4596-BBF5-CA03DD7B58CF@zwitserloot.com> Message-ID: <15e8b9d20906241923r65bba8b1x2cc27278971149a8@mail.gmail.com> On Wed, Jun 24, 2009 at 6:41 PM, Reinier Zwitserloot < reinier at zwitserloot.com> wrote: > Your general solution does not follow the suggested semantic of returning > effectively the same value that ends up in the map/list. For example, a map > that turns any null reference into a marker object would pass-through 'null' > and not 'MARKER'. It is therefore not a consistent solution. > Such a map violates the specification for java.util.Map. Other APIs may be indexable with a different specification, and a different implementation. This way of handling indexing can support both forms. Whichever semantics are decided to be appropriate for any given interface can be implemented without a change to the language specification. From ted at tedneward.com Wed Jun 24 19:38:35 2009 From: ted at tedneward.com (Ted Neward) Date: Wed, 24 Jun 2009 19:38:35 -0700 Subject: Indexing access for Lists and Maps: Don't Panic! In-Reply-To: <4A42BE13.7000604@sun.com> References: <4A42BE13.7000604@sun.com> Message-ID: <000801c9f53e$18783b80$4968b280$@com> +1. As Josh will be able to attest (or maybe not, his viewpoint might have been different from mine), the 175 EG was a lot like this, and honestly, I like what we came up with in the end, even if it wasn't everything I'd originally thought it would be *and* ended up to be more than I thought it could be. :-) Ted Neward | Principal Consultant, ThoughtWorks Java, .NET, XML Services Consulting, Teaching, Speaking, Writing http://www.thoughtworks.com | http://www.tedneward.com ? > -----Original Message----- > From: coin-dev-bounces at openjdk.java.net [mailto:coin-dev- > bounces at openjdk.java.net] On Behalf Of Joe Darcy > Sent: Wednesday, June 24, 2009 5:00 PM > To: coin-dev at openjdk.java.net > Subject: Indexing access for Lists and Maps: Don't Panic! > > Hello. > > A meta-comment on the voluminous email traffic about the potentially > puzzling semantics of the proposed setting indexing operators for Lists > and Maps: Don't Panic! > > Such issues being uncovered, analyzed, and subsequently fixed is an > expected part of language evolution. In my estimation, this is a > relatively minor problem that can be addressed in subsequent revisions > of the indexing proposal. > > -Joe From Joe.Darcy at Sun.COM Wed Jun 24 20:16:42 2009 From: Joe.Darcy at Sun.COM (Joe Darcy) Date: Wed, 24 Jun 2009 20:16:42 -0700 Subject: Indexing access for Lists and Maps: Don't Panic! In-Reply-To: <1057BEB2-7B58-4F03-8231-96558B4FC9C4@zwitserloot.com> References: <4A42BE13.7000604@sun.com> <1057BEB2-7B58-4F03-8231-96558B4FC9C4@zwitserloot.com> Message-ID: <4A42EC1A.9080301@sun.com> Reinier Zwitserloot wrote: > If this list can't figure it out, it seems somewhat presumptuous to > think that your average java programmer will. As this coin proposal is The average Java programmer is not asked to evaluate the semantics of a new, incomplete, in-progress potential language feature. A fraction of the 100 or so messages sent to the list on this matter over the last two days would have been sufficient to advance understanding of the problem and its possible solutions. -Joe > purely boilerplate removal, we should take care not to make the > boilerplate form more confusing than the original, lest we miss the > aim of this project entirely. > > --Reinier Zwitserloot > > > > On 2009/25/06, at 02:00, Joe Darcy wrote: > >> Hello. >> >> A meta-comment on the voluminous email traffic about the potentially >> puzzling semantics of the proposed setting indexing operators for >> Lists >> and Maps: Don't Panic! >> >> Such issues being uncovered, analyzed, and subsequently fixed is an >> expected part of language evolution. In my estimation, this is a >> relatively minor problem that can be addressed in subsequent revisions >> of the indexing proposal. >> >> -Joe >> > > From jan.kroken at gmail.com Thu Jun 25 03:36:01 2009 From: jan.kroken at gmail.com (Jan Kroken) Date: Thu, 25 Jun 2009 12:36:01 +0200 Subject: Proposal: Concise declaration of JavaBeans properties Message-ID: <73f3c7540906250336x3c77f5bby3b92228c5d451885@mail.gmail.com> PROJECT COIN SMALL LANGUAGE CHANGE PROPOSAL FORM v1.0 AUTHOR(S): Jan Kroken OVERVIEW Add syntactic sugar to reduce the amount of boilerplate code needed to adhere to the JavaBeans specification. FEATURE SUMMARY: Should be suitable as a summary in a language tutorial. Add a new field modifier, that will generate the neccessary JavaBeans methods at compile time. MAJOR ADVANTAGE: Significantly reduce the amount of boilerplate code in Java source code. MAJOR BENEFIT: Reducing the amount of boilerplate code will: - increase readability - reduce the amount of possible programming errors - reduce implementation and maintenance cost MAJOR DISADVANTAGE: The proposal will increase the complexity of the language. Methods will exist without having an explicit declaration, which may confuse programmers not familiar with the feature. ALTERNATIVES: The same feature can possibly be implemented using annotations and runtime code generation. EXAMPLES SIMPLE EXAMPLE: A value class in the current java language: public class MyValueObject { private Type1 field1; private Type2 field2; public void setField1(Type1 field1) { this.field1 = field1; } public Type1 getField1() { return field1; } public Type2 getField2() { return field2; } } The same value with the proposed language modification public class MyValueObject { private :exposed(rw) Type1 field1; private :exposed(r) Type2 field2; } Note that :exposed is not the suggested syntax modification. The exact notation should be decided upon by the working group. In the above example, :exposed(rw) will expose the value both through a getter and setter, while :exposed(r) will expose the value only through a getter. ADVANCED EXAMPLE: Any explicit declarations of a JavaBeans method in the current class will ensure that the method is not generated based on the field declaration. For instance, the class public class MyValueObject { private :exposed(rw) Type1 field1; private :exposed(r) Type2 field2; public void setField1(Type1 field1) { if(field1 == null) { throw new NullPointerException(); } this.field1 = field1; } } will be equivalent to public class MyValueObject { private Type1 field1; private Type2 field2; public void setField1(Type1 field1) { if(field1 == null) { throw new NullPointerException(); } this.field1 = field1; } public Type1 getField1() { return field1; } public Type2 getField2() { return field2; } } DETAILS SPECIFICATION: A modifier, currently represented by :exposed(specification), should be added to class fields. The modifier has two optional arguments, r (read) and w (write). a read argument specifies that the compiler should generate public JavaBeans read methods for the field. The write argument specifies that the compiler should generate a public JavaBeans set method for the field. If the field is a boolean field, both a getField and a isField method will be generated. If one of those are declared in the current class, none will be generated. This is to avoid a loophole where a transformation is added to one of those, while the field is accidentally made available through the other. if no arguments are provided, both read and write methods will be generated. Any explicit declarations of a JavaBeans method in the current class will ensure that the method is not generated based on the field declaration. If a field is declared as an exposed, and there is a conflict with JavaBeans methods implemented in a superclass, the JavaBeans methods will be generated, and override the ones declared in the superclass. The added field modifier should be chosen so it does not conflict with any existing Java source code. The change would be implemented as desugaring at compile time. The class file format or type system will not be affected. The effect this change will have on stack trace information and debugging information has not been analyzed. TESTING: It will be possible to create test code with a full coverage of all variants. LIBRARY SUPPORT: There is no need for library support. REFLECTIVE APIS: This change will not require changes to the reflection apis. OTHER CHANGES: The only component that needs to be modified is the compiler. MIGRATION: Sketch how a code base could be converted, manually or automatically, to use the new feature. A class could be modified through a series of transformations: if there is a setter that matches the JavaBeans specification for a field, and the setter does not contain any other operations than assigning the field to the passed arguemnt, then the setter can be removed, and the modifier :exposed(w) be added to the field declaration. if there is a getter that matches the JavaBeans specification, the getter only returns the field value without performing any other operations, and there is not another getter not complying with these criteria, the getter(s) can be removed, and the modifier :exposed(r) be added to the field declaration. redundant occurences of :exposed(r) or :exposed(w) in one field declaration should be removed. If a field declaration has both an :exposed(r) and an :exposed(w) modifier, both should be removed and replaced with a modifier :exposed. COMPATIBILITY BREAKING CHANGES: No existing java programs will break. However, parsers, compilers and source analyzing applications for the java language will break, and have to be modified. EXISTING PROGRAMS: There will be no changes in behaviour for existing programs, neither class files nor programs compiled from source. REFERENCES EXISTING BUGS: URL FOR PROTOTYPE (optional): No prototype at this time. From reinier at zwitserloot.com Thu Jun 25 06:38:02 2009 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Thu, 25 Jun 2009 15:38:02 +0200 Subject: Proposal: Concise declaration of JavaBeans properties In-Reply-To: <73f3c7540906250336x3c77f5bby3b92228c5d451885@mail.gmail.com> References: <73f3c7540906250336x3c77f5bby3b92228c5d451885@mail.gmail.com> Message-ID: You're 2.5 months too late with a proposal. Also, I recall similar proposals having been suggested during the official proposal period (which was the month of march). They did not make the shortlist, for some reason. --Reinier Zwitserloot On 2009/25/06, at 12:36, Jan Kroken wrote: > PROJECT COIN SMALL LANGUAGE CHANGE PROPOSAL FORM v1.0 > > AUTHOR(S): Jan Kroken > > OVERVIEW > > Add syntactic sugar to reduce the amount of boilerplate code needed > to adhere to the JavaBeans specification. > > FEATURE SUMMARY: Should be suitable as a summary in a language > tutorial. > > Add a new field modifier, that will generate the neccessary > JavaBeans > methods at compile time. > > MAJOR ADVANTAGE: > > Significantly reduce the amount of boilerplate code in Java > source code. > > MAJOR BENEFIT: > > Reducing the amount of boilerplate code will: > - increase readability > - reduce the amount of possible programming errors > - reduce implementation and maintenance cost > > MAJOR DISADVANTAGE: > > The proposal will increase the complexity of the language. > Methods will > exist without having an explicit declaration, which may confuse > programmers > not familiar with the feature. > > ALTERNATIVES: > > The same feature can possibly be implemented using annotations and > runtime code generation. > > EXAMPLES > > SIMPLE EXAMPLE: > > A value class in the current java language: > > public class MyValueObject { > private Type1 field1; > private Type2 field2; > > public void setField1(Type1 field1) { > this.field1 = field1; > } > > public Type1 getField1() { > return field1; > } > > public Type2 getField2() { > return field2; > } > } > > The same value with the proposed language modification > > public class MyValueObject { > private :exposed(rw) Type1 field1; > private :exposed(r) Type2 field2; > } > > Note that :exposed is not the suggested syntax modification. > The exact notation should be decided upon by the working group. > > In the above example, :exposed(rw) will expose the value both > through a getter and setter, while :exposed(r) will expose the > value only through a getter. > > ADVANCED EXAMPLE: > > Any explicit declarations of a JavaBeans method in the current > class > will ensure that the method is not generated based on the field > declaration. > > For instance, the class > > public class MyValueObject { > private :exposed(rw) Type1 field1; > private :exposed(r) Type2 field2; > > public void setField1(Type1 field1) { > if(field1 == null) { > throw new NullPointerException(); > } > this.field1 = field1; > } > } > > will be equivalent to > > public class MyValueObject { > private Type1 field1; > private Type2 field2; > > public void setField1(Type1 field1) { > if(field1 == null) { > throw new NullPointerException(); > } > this.field1 = field1; > } > > public Type1 getField1() { > return field1; > } > > public Type2 getField2() { > return field2; > } > } > > DETAILS > > SPECIFICATION: > > A modifier, currently represented by :exposed(specification), > should be added to class fields. > > The modifier has two optional arguments, r (read) and w (write). > a read argument specifies that the compiler should generate > public JavaBeans read methods for the field. The write argument > specifies that the compiler should generate a public JavaBeans > set method for the field. > > If the field is a boolean field, both a getField and a isField > method will be generated. If one of those are declared in the > current class, none will be generated. This is to avoid a loophole > where a transformation is added to one of those, while the field > is accidentally made available through the other. > > if no arguments are provided, both read and write methods will > be generated. > > Any explicit declarations of a JavaBeans method in the current > class > will ensure that the method is not generated based on the field > declaration. > > If a field is declared as an exposed, and there is a conflict with > JavaBeans methods implemented in a superclass, the JavaBeans > methods > will be generated, and override the ones declared in the > superclass. > > The added field modifier should be chosen so it does not conflict > with any existing Java source code. > > The change would be implemented as desugaring at compile time. The > class file format or type system will not be affected. > > The effect this change will have on stack trace information and > debugging information has not been analyzed. > > > TESTING: > > It will be possible to create test code with a full coverage of all > variants. > > LIBRARY SUPPORT: > > There is no need for library support. > > REFLECTIVE APIS: > > This change will not require changes to the reflection apis. > > OTHER CHANGES: > > The only component that needs to be modified is the compiler. > > MIGRATION: Sketch how a code base could be converted, manually or > automatically, to use the new feature. > > A class could be modified through a series of transformations: > > if there is a setter that matches the JavaBeans specification for a > field, and the setter does not contain any other operations than > assigning > the field to the passed arguemnt, then the setter can be removed, > and > the modifier :exposed(w) be added to the field declaration. > > if there is a getter that matches the JavaBeans specification, the > getter > only returns the field value without performing any other > operations, > and > there is not another getter not complying with these criteria, the > getter(s) can be removed, and the modifier :exposed(r) be added > to the > field declaration. > > redundant occurences of :exposed(r) or :exposed(w) in one field > declaration should be removed. > > If a field declaration has both an :exposed(r) and an :exposed(w) > modifier, both should be removed and replaced with a modifier > :exposed. > > > COMPATIBILITY > > BREAKING CHANGES: > > No existing java programs will break. However, parsers, compilers > and > source analyzing applications for the java language will break, > and have > to be modified. > > EXISTING PROGRAMS: > > There will be no changes in behaviour for existing programs, > neither > class files nor programs compiled from source. > > REFERENCES > > EXISTING BUGS: > > URL FOR PROTOTYPE (optional): > > No prototype at this time. > From Joe.Darcy at Sun.COM Thu Jun 25 10:40:02 2009 From: Joe.Darcy at Sun.COM (Joe Darcy) Date: Thu, 25 Jun 2009 10:40:02 -0700 Subject: Proposal: Concise declaration of JavaBeans properties In-Reply-To: References: <73f3c7540906250336x3c77f5bby3b92228c5d451885@mail.gmail.com> Message-ID: <4A43B672.40600@sun.com> Yes, this proposal is long overdue and will not be considered for JDK 7. -Joe Reinier Zwitserloot wrote: > You're 2.5 months too late with a proposal. Also, I recall similar > proposals having been suggested during the official proposal period > (which was the month of march). They did not make the shortlist, for > some reason. > > --Reinier Zwitserloot > > > > On 2009/25/06, at 12:36, Jan Kroken wrote: > >> PROJECT COIN SMALL LANGUAGE CHANGE PROPOSAL FORM v1.0 >> >> AUTHOR(S): Jan Kroken >> >> OVERVIEW >> >> Add syntactic sugar to reduce the amount of boilerplate code needed >> to adhere to the JavaBeans specification. >> >> FEATURE SUMMARY: Should be suitable as a summary in a language >> tutorial. >> >> Add a new field modifier, that will generate the neccessary >> JavaBeans >> methods at compile time. >> >> MAJOR ADVANTAGE: >> >> Significantly reduce the amount of boilerplate code in Java >> source code. >> >> MAJOR BENEFIT: >> >> Reducing the amount of boilerplate code will: >> - increase readability >> - reduce the amount of possible programming errors >> - reduce implementation and maintenance cost >> >> MAJOR DISADVANTAGE: >> >> The proposal will increase the complexity of the language. >> Methods will >> exist without having an explicit declaration, which may confuse >> programmers >> not familiar with the feature. >> >> ALTERNATIVES: >> >> The same feature can possibly be implemented using annotations and >> runtime code generation. >> >> EXAMPLES >> >> SIMPLE EXAMPLE: >> >> A value class in the current java language: >> >> public class MyValueObject { >> private Type1 field1; >> private Type2 field2; >> >> public void setField1(Type1 field1) { >> this.field1 = field1; >> } >> >> public Type1 getField1() { >> return field1; >> } >> >> public Type2 getField2() { >> return field2; >> } >> } >> >> The same value with the proposed language modification >> >> public class MyValueObject { >> private :exposed(rw) Type1 field1; >> private :exposed(r) Type2 field2; >> } >> >> Note that :exposed is not the suggested syntax modification. >> The exact notation should be decided upon by the working group. >> >> In the above example, :exposed(rw) will expose the value both >> through a getter and setter, while :exposed(r) will expose the >> value only through a getter. >> >> ADVANCED EXAMPLE: >> >> Any explicit declarations of a JavaBeans method in the current >> class >> will ensure that the method is not generated based on the field >> declaration. >> >> For instance, the class >> >> public class MyValueObject { >> private :exposed(rw) Type1 field1; >> private :exposed(r) Type2 field2; >> >> public void setField1(Type1 field1) { >> if(field1 == null) { >> throw new NullPointerException(); >> } >> this.field1 = field1; >> } >> } >> >> will be equivalent to >> >> public class MyValueObject { >> private Type1 field1; >> private Type2 field2; >> >> public void setField1(Type1 field1) { >> if(field1 == null) { >> throw new NullPointerException(); >> } >> this.field1 = field1; >> } >> >> public Type1 getField1() { >> return field1; >> } >> >> public Type2 getField2() { >> return field2; >> } >> } >> >> DETAILS >> >> SPECIFICATION: >> >> A modifier, currently represented by :exposed(specification), >> should be added to class fields. >> >> The modifier has two optional arguments, r (read) and w (write). >> a read argument specifies that the compiler should generate >> public JavaBeans read methods for the field. The write argument >> specifies that the compiler should generate a public JavaBeans >> set method for the field. >> >> If the field is a boolean field, both a getField and a isField >> method will be generated. If one of those are declared in the >> current class, none will be generated. This is to avoid a loophole >> where a transformation is added to one of those, while the field >> is accidentally made available through the other. >> >> if no arguments are provided, both read and write methods will >> be generated. >> >> Any explicit declarations of a JavaBeans method in the current >> class >> will ensure that the method is not generated based on the field >> declaration. >> >> If a field is declared as an exposed, and there is a conflict with >> JavaBeans methods implemented in a superclass, the JavaBeans >> methods >> will be generated, and override the ones declared in the >> superclass. >> >> The added field modifier should be chosen so it does not conflict >> with any existing Java source code. >> >> The change would be implemented as desugaring at compile time. The >> class file format or type system will not be affected. >> >> The effect this change will have on stack trace information and >> debugging information has not been analyzed. >> >> >> TESTING: >> >> It will be possible to create test code with a full coverage of all >> variants. >> >> LIBRARY SUPPORT: >> >> There is no need for library support. >> >> REFLECTIVE APIS: >> >> This change will not require changes to the reflection apis. >> >> OTHER CHANGES: >> >> The only component that needs to be modified is the compiler. >> >> MIGRATION: Sketch how a code base could be converted, manually or >> automatically, to use the new feature. >> >> A class could be modified through a series of transformations: >> >> if there is a setter that matches the JavaBeans specification for a >> field, and the setter does not contain any other operations than >> assigning >> the field to the passed arguemnt, then the setter can be removed, >> and >> the modifier :exposed(w) be added to the field declaration. >> >> if there is a getter that matches the JavaBeans specification, the >> getter >> only returns the field value without performing any other >> operations, >> and >> there is not another getter not complying with these criteria, the >> getter(s) can be removed, and the modifier :exposed(r) be added >> to the >> field declaration. >> >> redundant occurences of :exposed(r) or :exposed(w) in one field >> declaration should be removed. >> >> If a field declaration has both an :exposed(r) and an :exposed(w) >> modifier, both should be removed and replaced with a modifier >> :exposed. >> >> >> COMPATIBILITY >> >> BREAKING CHANGES: >> >> No existing java programs will break. However, parsers, compilers >> and >> source analyzing applications for the java language will break, >> and have >> to be modified. >> >> EXISTING PROGRAMS: >> >> There will be no changes in behaviour for existing programs, >> neither >> class files nor programs compiled from source. >> >> REFERENCES >> >> EXISTING BUGS: >> >> URL FOR PROTOTYPE (optional): >> >> No prototype at this time. >> > > From reinier at zwitserloot.com Thu Jun 25 12:46:07 2009 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Thu, 25 Jun 2009 21:46:07 +0200 Subject: A simple solution for [] access that can trivially be added to List and Map. Message-ID: Step 1: "Allow returning anything when overriding or hiding a method that returns void". This change involves rule 8.4.8.3 of JLS 3. Rule 8.4.8.3 allows you to override a method with e.g. signature "Number foo()" with a method that returns Integer. The clue here is that Integers are also Numbers (because Integer is a subtype of Number). We expand rule 8.4.8.3 to add: If a method declaration d1 overrides or hides another method d2, where d2 has return type 'void', then d1 may return any type, including primitives and void. Step 2: "Create SetIndex, GetIndex, SetWithKey, and GetWithKey interfaces". We create the java.lang.operators package, which will hold interfaces that let types (re)define the meaning of operators employed on instances of their type. The java.lang namespace is 'special', in that all source files import it implicitly, so adding new items to it should not be undertaken lightly. Yet, the java.lang.operators package clearly shows that it is a fundamental aspect of the java language by being a sub-package of java.lang; see also java.lang.annotation.Annotation which is similarly 'magic' (in that any public @interface silently implements that interface). Inside this package we add the following 4 interfaces: public interface SetIndex { public void set(int idx, V value); } public interface GetIndex { public V get(int idx); } public interface SetWithKey { public void put(K key, V value); } public interface GetWithKey { public V get(K key); } java.util.Map will then add 'GetWithKey, SetWithKey' to its implements list. java.util.List will then add 'GetIndex, SetIndex ' to its implements list. Those additions are backwards and migration compatible, due to step 1, which legally allows both map and list's existing set/put methods to return something, even though in the SetIndex/SetWithKey interfaces, set/put return void. All existing class files that implement List and/ or Map will seamlessly support the indexing operations, and any existing source code that implements Map or List or a child interface/ class thereof continue to compile to the same semantic meaning without introducing any (new) errors and warnings. Step 3) Define how operator overloading interacts with the language. (The method calls in this section are given as how they are represented in the class file format; that is, the methods are fully typed). We now expand the meaning of: foo[bar] Depending on context (on the LHS of any assignment operation, so '=', '+=', '|=', etcetera, as context 'set', and anywhere else as context 'get'). 'set' context: foo[bar] = RHS is translated to 2 potential method calls: (ONLY if foo is assignable to SetIndex) method: java/lang/operators/SetIndex.set receiver: foo args: bar, RHS and: (ONLY if foo is assignable to SetWithKey) method: java/lang/operators/SetWithKey.put receiver: foo args: bar, RHS In the event foo implements *BOTH* SetIndex and SetWithKey, resolution is analogous as if both methods had the same name; there is no method selection ambiguity because SetWithKey's first argument is neccessarily a class type, whereas SetIndex's first arg is a primitive, int. In other words, resolution would occur analogous to how resolution occurs in the following class: class Example { void foo(int x) {} void foo(T x) {} public static void main(String[] args) { Example ex = new Example(); ex.foo(10); ex.foo(Integer.valueOf(10)); } } The specifics for how such calls are resolved can be found in the JLS3, for example section 5.1.8, "Unboxing conversion" (as the only possible confusion here is when an Integer object may or may not unbox to int to call set, or an int primitives boxes to Integer to call put). 'get' context: Analogous to the 'set' context, except translates to GetIndex.get and GetWithKey.get. See Appendix B for a defense of why 4 methods are needed and not 2. APPENDIX A: Defense of allowing the return of any value when overriding methods of void. Currently, rule 8.4.8.3 is implemented by javac by producing 2 methods: The actual defined method with the tightened return type, and a synthetic wrapper method with the original signature, that simply forwards the call to the real method. This way, any callers that don't know about the return type tightening still end up with the right result. See the JVM spec section on 'method descriptions' on how the JVM resolves method invocations, which shows why rule 8.4.8.3, which was introduced in java 1.5 (or even java 1.6?) is backwards and migration compatible. The exact same strategy can be implemented in order to let a subclass provide a return type on a method when the parent class returns void: The actual method with the return type is put in the class file as normal, then a synthetic wrapper method with return type void is also added, which simply calls the real method. The only difference is that this method just calls the real method, and returns nothing, whereas the current 8.4.8.3 rule calls the real method and returns what it returns. The 'void' type is effectively a supertype of everything: After all, 'being a subtype of' implies that any instances of that type can be substituted for the supertype. Clearly any object or primitive can be 'substituted' for the void type: Simply bitbucket the primitive or object. In this sense, rule 8.4.8.3's current exclusion of the 'void' mechanic is in fact an inconsistency in the java language spec. Entirely analogous to 8.4.8.3, the purpose of this relaxation of the rules is to increase the flexibility of API design. We let APIs tighten the return type in order to have each level in a hierarchy of types have the most appropriate semantics. The void case is no different. Lastly, there is no existing code, compiled or in source form, that is legal now that would not be legal after this change, or that would change semantics. After all, any method that overrides a 'returns void' method must currently have the 'void' return type, or it wouldn't compile. APPENDIX B: Why 4 types and not 2? The pragmatic reason of fitting both Map's put and List's set method is the most important, but the operation of putting an entry in a mapping and accessing the index of a list-like construct are semantically not the same and should therefore not be lumped into a single interface. Consider for example that 'List.set' is documented to throw an IndexOutOfBoundsException, which seems to be a good fit even for 'SetIndex', whereas it makes absolutely no sense for a put operation. Semantically speaking then, foo[x] where foo is a Map, and foo[x] where foo is a List, just aren't the same operation. They merely have a similar feel. This situation is not unprecedented; in java, the + operation can mean either string concatenation or numeric addition. While they feel somewhat similar and both operations are routinely represented with the '+' symbol in many languages, the operations aren't the same. string concatenation isn't commutative, whereas numeric addition is! The third reason is that no ambiguity can arise; the compiler will always know which form is intended (WithKey, or Index). Because indexed operations work with primitives, and map key storage works with objects, any given 'foo[bar]' style assignment or retrieval operation can always be resolved to be either SetIndex/GetIndex or SetWithKey/GetWithKey, even in the unlikely event that 'foo' implements both interfaces. MAJOR DISADVANTAGE: The notion that assignments, 'for consistency's sake', should themselves be an expression that returns a value, eventhough there's considerable confusion as to what ought to be returned, seems to be an obvious candidate for a disadvantage of this proposal, as this proposal returns 'void' for assignment operators. The author believes this is in fact desired behaviour: *because* of the confusion around what such an assignment ought to return, it is expected that the nature of the returned value will often be misunderstood. By returning nothing, any misunderstanding is caught early with a clear error message, instead of late, without an error message, and without even a stack trace to aid in debugging. This proposal does not aim to make list access and array access consistent. In order to do this, list access must also be retrofitted so that: foo.length where foo is a list, actually calls the size() method, which seems to be far beyond Project Coin's stated goals. Some sort of 'autoboxing' of lists into arrays and vice versa when calling methods that expect lists or arrays is also required to make them consistent, as well as reification of generics, AND fixing array's different (more permissive) behaviour for contravariancy. Clearly such a goal is utterly unatainable within the confines of Project Coin, and therefore this proposal does not take such consistency into consideration. If the disadvantage of returning nothing is deemed to great, an alternative can be posited: The SetWithKey and SetIndex interfaces do not change, but the desugaring of foo[bar] does change: foo[bar] = RHS will first retrofit RHS so that it 'fits' into foo (e.g. apply autoboxing or unboxing), then this post-capture value is passed on the set/put method, and is duplicated on the stack as well for further consumption. This solution has the exact same effect as Neal Gafter's suggestion to desugar '[]' to a static method which you must then import, along with the following static method in java.util.Collections: public static V operator_index_put(Map map, K key, V value) { map.put(key, value); return value; } --Reinier Zwitserloot From reinier at zwitserloot.com Thu Jun 25 15:17:52 2009 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Fri, 26 Jun 2009 00:17:52 +0200 Subject: A simple solution for [] access that can trivially be added to List and Map. In-Reply-To: <200906252355.28516.peter.levart@gmail.com> References: <200906252355.28516.peter.levart@gmail.com> Message-ID: <68B7A388-6E70-49F0-88BE-E05EE88D9882@zwitserloot.com> Ulf: yes, my interface names sucked. Yours are better, though I believe the more accepted spelling is two T's (PuttableByKey, not PutableByKey). Peter: Replies inline On 2009/25/06, at 23:55, Peter Levart wrote: > Considering your extension of rule 8.4.8.3 this is not always the > case. Anything can be returned. It depends on the static type of the > receiver and what that type defines as a set/put method's return type. True, but, as the proposal states, the actual method invoked is ALWAYS the variant in PuttableByIndex or PuttableByKey; in other words, the invoked method is always the wrapper that returns void - if you do return something, and you use [] in the set/put context, whatever you return is neccessarily thrown away. It may help to imagine that this: foo[bar] = RHS; desugars to, after figuring out whether PuttableByIndex or PuttableByKey is intended: ((PuttableByIndex)foo).set(bar, RHS); Note the cast - it ensures the expression's type is void, even if 'foo' has a type that does return a value out of the put/set method. Because the API consideration of returning a value out of the put/set call is now no longer a part of PuttableByKey/SettableByIndex, each implementation that chooses to return something other than void gets to define their own semantics. We don't have to come up with 1 semantic that must fit all implementations. We also preclude such a semantic to ever be used together with the [] assignment access, but I can live with that. We're still talking about, as Ruslan showed, a vanishingly small number of code-lines where pass-through assignment is even an issue. > > This does not apply because of the above. So I think it is important > that... > ... so, it _does_ apply, and I still think the 'returns void' scenario is the best choice here. Nevertheless.... > > > > foo[bar] = RHS > > > > will first retrofit RHS so that it 'fits' into foo (e.g. apply > > autoboxing or unboxing), then this post-capture value is passed on > the > > set/put method, and is duplicated on the stack as well for further > > consumption. > > With this, everybody can be happy. > Yes, I admit that 'return void' appears to be a small minority here. From neal at gafter.com Thu Jun 25 15:32:27 2009 From: neal at gafter.com (Neal Gafter) Date: Thu, 25 Jun 2009 15:32:27 -0700 Subject: A simple solution for [] access that can trivially be added to List and Map. In-Reply-To: References: Message-ID: <15e8b9d20906251532j3bac90b7qc0f192aa33f7d05f@mail.gmail.com> On Thu, Jun 25, 2009 at 12:46 PM, Reinier Zwitserloot wrote: > Those additions are backwards and migration compatible, due to step 1, > which legally allows both map and list's existing set/put methods to > return something, even though in the SetIndex/SetWithKey interfaces, > set/put return void. All existing class files that implement List and/ > or Map will seamlessly support the indexing operations, and any > existing source code that implements Map or List or a child interface/ > class thereof continue to compile to the same semantic meaning without > introducing any (new) errors and warnings. Unfortunately, this strategy isn't binary compatible. In order to allow this new form of "covariant" returns, the compiler will need to produce bridge methods in the implementation of every Map and List class. Existing class files simply don't contain those bridge methods today. -Neal From lk at teamten.com Thu Jun 25 15:35:03 2009 From: lk at teamten.com (Lawrence Kesteloot) Date: Thu, 25 Jun 2009 15:35:03 -0700 Subject: A simple solution for [] access that can trivially be added to List and Map. In-Reply-To: <68B7A388-6E70-49F0-88BE-E05EE88D9882@zwitserloot.com> References: <200906252355.28516.peter.levart@gmail.com> <68B7A388-6E70-49F0-88BE-E05EE88D9882@zwitserloot.com> Message-ID: <997cab100906251535v2ccf3f1ct19a876290a3cabbc@mail.gmail.com> Reinier wrote: > We're still talking about, as Ruslan showed, a > vanishingly small number of code-lines where pass-through assignment > is even an issue. Ruslan only checked compound assignment (a = b = c). What about my idiomatic assignment-in-while: do { x = read(); } while ((list[i++] = x) != terminatingValue); or, more concisely: while ((list[i++] = read()) != terminatingValue) { ... } I used to see this all the time in C, but haven't seen it much in Java. I like your proposal. Compared to Neal's static import, however, it seems more invasive (void-return change) and less flexible (the assignment can't decide what to return). The void-return change, in particular, smells bad. Lawrence From reinier at zwitserloot.com Thu Jun 25 15:52:27 2009 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Fri, 26 Jun 2009 00:52:27 +0200 Subject: A simple solution for [] access that can trivially be added to List and Map. In-Reply-To: <15e8b9d20906251532j3bac90b7qc0f192aa33f7d05f@mail.gmail.com> References: <15e8b9d20906251532j3bac90b7qc0f192aa33f7d05f@mail.gmail.com> Message-ID: Er, right. Scratch that idea. Well, that, or we allow some sort of post-processing in the class loader, so that any class that flies by is instrumented with the appropriate synthetic wrappers if they aren't there. NB: Lawrence, asking users to import static stuff isn't exactly something to just dance around. That's quite a big concern. I'd personally rate [] support 'hardcoded' onto java.util.List and java.util.Map as a far better plan than forcing static imports just to make [] work. --Reinier Zwitserloot On 2009/26/06, at 00:32, Neal Gafter wrote: > On Thu, Jun 25, 2009 at 12:46 PM, Reinier > Zwitserloot wrote: >> Those additions are backwards and migration compatible, due to step >> 1, >> which legally allows both map and list's existing set/put methods to >> return something, even though in the SetIndex/SetWithKey interfaces, >> set/put return void. All existing class files that implement List >> and/ >> or Map will seamlessly support the indexing operations, and any >> existing source code that implements Map or List or a child >> interface/ >> class thereof continue to compile to the same semantic meaning >> without >> introducing any (new) errors and warnings. > > Unfortunately, this strategy isn't binary compatible. In order to > allow this new form of "covariant" returns, the compiler will need to > produce bridge methods in the implementation of every Map and List > class. Existing class files simply don't contain those bridge methods > today. > > -Neal From Ulf.Zibis at gmx.de Thu Jun 25 16:11:52 2009 From: Ulf.Zibis at gmx.de (Ulf Zibis) Date: Fri, 26 Jun 2009 01:11:52 +0200 Subject: A simple solution for [] access that can trivially be added to List and Map. In-Reply-To: References: Message-ID: <4A440438.1090205@gmx.de> Added my post to coin-dev at openjdk.java.net via CC: ... I more would like: public interface SetableByIndex { public void set(int idx, V value); } public interface GetableByIndex { public V get(int idx); } public interface PutableByKey { public void put(K key, V value); } public interface GetableByKey { public V get(K key); } .. or shorter: public interface IndexSetable { public void set(int idx, V value); } public interface IndexGetable { public V get(int idx); } public interface KeyPutable { public void put(K key, V value); } public interface KeyGetable { public V get(K key); } -Ulf From rssh at gradsoft.com.ua Thu Jun 25 11:48:38 2009 From: rssh at gradsoft.com.ua (Ruslan Shevchenko) Date: Thu, 25 Jun 2009 21:48:38 +0300 (EEST) Subject: indexed access: 10 ways to fix 'harmfull' issue Message-ID: <51e42409ab3c01a7949f170020548431.squirrel@wmail.gradsoft.ua> 10 ways, collected from discussions: 1. Do nothing. Say, that it's a feature, not bug to have funny questions for intervies. x[i]=q is shortcut for x.put(i,q) looks strange from some point of view : yes backward compability: yes extra overhead: no limited functionality:no //Comment: php people just added goto to version 5.3 and start thinking about cobol 'alter'. May be they know something ? 2. Do nothing, but produce a warning when indexed assigment take part in compound assigment looks strange from some point of view : yes, but better then previous backward compability: yes extra overhead: no limited functionality: yes //Comment: usefull operation of swapping two elements in map will cause warning. //2.1. recognize this operation and does not produce warning. 3. Change semantics in assigment in that way, that indexed assigment also return value of right part, casted to type of left part. looks strange from some point of view : minor: // (x[i]=b)==x[i] can be not always true, becouse we return right part instead left. Map x = new HashMap(); if ((x[1]=128)==x[1]) { System.err.println("eq"); } else { System.err.println("neq"); } will print neq. int[] x = new int[1]; if ((x[1]=128)==x[1]) { System.err.println("eq"); } else { System.err.println("neq"); } will print eq. backward compability: yes (if will not change rules for arrays and variables) extra overhead: no limited functionality: no //Comment: some existing statements of JLS will be changed, but for arrays and plain variables // we have choise: left the same as previous, 4. Forse result of indexed assigment be void. Therefore, it would be not possible use indexed assigment as part of compound assigment. looks strange from some point of view : yes. backward compability: yes extra overhead: no limited functionality: yes 5. Implements only getters. looks strange from some point of view : yes. backward compability: yes extra overhead: no limited functionality: yes 6. Retrofit interface (with operations like getByKey and setByKey) which return just-setted values instead previously setted. And use setByKey() instead put. Implement setByKey in AbstractMap, AbstractList looks strange: no backward compability: no (but changes are minimal: only user implementation of Collections, which are not derived from AbstractMap or AbstractList, will be touched and fix [implementing setByKey()] will be trivial) extra overhead: no limited functionality: no Comment: I think, that if major language version is changed, than it is possible to introduce incompabilities. 7. Implement in Collections static method indexed_set_assigment, which will look like: indexed_set_assigment(Map map, K k, V v) { map.put(k,v); return v; } and let compiler will call this method during desugaring of compound assigment. looks strange from some point of view : minor (same as 3). backward compability: yes. extra overhead: no limited functionality: no Also introduce small interface for 'less-then-collections' indexed access. 8. Implement in Collections static method indexed_set_assigment, which will look like: indexed_set_assigment(Map map, K k, V v) { map.put(k,v); return map.get(k); } and then same as 7. looks strange from some point of view : yes, if get have side-effects, than they will unexpected backward compability: yes. extra overhead: yes (but if call will be only during participation of compound assigments - it will be rare) limited functionality: no 9. Desugar (x[i]=y) as x.put(i,y); x.get(i) // same as 8, but inline without extra method in library. looks strange from some point of view : yes, if get have side-effects, than they will unexpected backward compability: yes. extra overhead: yes (but if call will be only during participation of compound assigments - it will be rare) limited functionality: no 10. Change overriding rules, to allow override void methods by methods with other return types. then retrofit set of such interfaces on list and map, than define semantics of compound assigment as in 7 looks strange from some point of view : yes, changes to override semantics +minor (same as 3). backward compability: yes. extra overhead: no limited functionality: no // looks like 3, but with changes to inheritance for purpose of defining semantics of indexed assigment // in uniform manner for collections and non-collections. ------------- All of this (may be except 10, 9, 8) can be acceptable in some way. Is I missed something ? From rssh at gradsoft.com.ua Thu Jun 25 11:52:04 2009 From: rssh at gradsoft.com.ua (Ruslan Shevchenko) Date: Thu, 25 Jun 2009 21:52:04 +0300 (EEST) Subject: A simple solution for [] access that can trivially be added to List and Map. In-Reply-To: <997cab100906251535v2ccf3f1ct19a876290a3cabbc@mail.gmail.com> References: <200906252355.28516.peter.levart@gmail.com> <68B7A388-6E70-49F0-88BE-E05EE88D9882@zwitserloot.com> <997cab100906251535v2ccf3f1ct19a876290a3cabbc@mail.gmail.com> Message-ID: > Reinier wrote: >> We're still talking about, as Ruslan showed, a >> vanishingly small number of code-lines where pass-through assignment >> is even an issue. > > Ruslan only checked compound assignment (a = b = c). What about my > idiomatic assignment-in-while: > > do { > x = read(); > } while ((list[i++] = x) != terminatingValue); > > or, more concisely: > > while ((list[i++] = read()) != terminatingValue) { ... } > > I used to see this all the time in C, but haven't seen it much in Java. > Ohh, My fault. > I like your proposal. Compared to Neal's static import, however, it > seems more invasive (void-return change) and less flexible (the > assignment can't decide what to return). The void-return change, in > particular, smells bad. > > Lawrence > > From abies at adres.pl Thu Jun 25 22:23:30 2009 From: abies at adres.pl (Artur Biesiadowski) Date: Fri, 26 Jun 2009 07:23:30 +0200 Subject: indexed access: 10 ways to fix 'harmfull' issue In-Reply-To: <51e42409ab3c01a7949f170020548431.squirrel@wmail.gradsoft.ua> References: <51e42409ab3c01a7949f170020548431.squirrel@wmail.gradsoft.ua> Message-ID: <4A445B52.8000602@adres.pl> Ruslan Shevchenko wrote: > 3. Change semantics in assigment in that way, that indexed assigment also > return value of right part, casted > to type of left part. > looks strange from some point of view : minor: > // (x[i]=b)==x[i] can be not always true, becouse we return right part > instead left. > > Map x = new HashMap(); > if ((x[1]=128)==x[1]) { > System.err.println("eq"); > } else { > System.err.println("neq"); > } > will print neq. > > int[] x = new int[1]; > if ((x[1]=128)==x[1]) { > System.err.println("eq"); > } else { > System.err.println("neq"); > } > will print eq. > > backward compability: yes (if will not change rules for arrays and > variables) > extra overhead: no > limited functionality: no > > //Comment: some existing statements of JLS will be changed, but for arrays > and plain variables > // we have choise: left the same as previous, > As far as I understand it, your upper example will also return eq. 128 will be autoboxed to Integer, then duplicated on stack, then put into x[1] and then compared to value got from x[1]. Additionally, don't use x[1] on array of length 1 ;) I think that better example to show the confusion is Integer x,z int y; z = 1000; x = (y = z); then x != z Which is the case currently. Same way for possible map syntax. Map map; int y; map[1] = 1000; map[0] = (y = map[1]); then map[0] != map[1] While it is maybe not the most obvious behaviour, it is exactly the same thing as we observe today (see Integer example above). As far as I understand, it is specified exactly this way in JLS, so this option actually means "don't change anything in JLS". Same example as above can be also applied for Integer[] array. Integer[] x = new Integer[1]; System.out.println(x[0] == (x[0]=1000)); is false currently. Regards, Artur Biesiadowski From rssh at gradsoft.com.ua Thu Jun 25 17:39:47 2009 From: rssh at gradsoft.com.ua (Ruslan Shevchenko) Date: Fri, 26 Jun 2009 03:39:47 +0300 (EEST) Subject: indexed access: 10 ways to fix 'harmfull' issue In-Reply-To: <4A445B52.8000602@adres.pl> References: <51e42409ab3c01a7949f170020548431.squirrel@wmail.gradsoft.ua> <4A445B52.8000602@adres.pl> Message-ID: <78d6653b10c8a550b8bb44fd38ab43ef.squirrel@wmail.gradsoft.ua> > Ruslan Shevchenko wrote: >> 3. Change semantics in assigment in that way, that indexed assigment >> also >> return value of right part, casted >> to type of left part. >> looks strange from some point of view : minor: >> // (x[i]=b)==x[i] can be not always true, becouse we return right part >> instead left. >> >> Map x = new HashMap(); >> if ((x[1]=128)==x[1]) { >> System.err.println("eq"); >> } else { >> System.err.println("neq"); >> } >> will print neq. >> >> int[] x = new int[1]; >> if ((x[1]=128)==x[1]) { >> System.err.println("eq"); >> } else { >> System.err.println("neq"); >> } >> will print eq. >> >> backward compability: yes (if will not change rules for arrays and >> variables) >> extra overhead: no >> limited functionality: no >> >> //Comment: some existing statements of JLS will be changed, but for >> arrays >> and plain variables >> // we have choise: left the same as previous, >> > > As far as I understand it, your upper example will also return eq. 128 > will be autoboxed to Integer, then duplicated on stack, then put into > x[1] and then compared to value got from x[1]. Additionally, don't use Exists two ways for compiler to return right part. 1: do autoboxing, than duplicate received integer on stack, than call method. 2: call put (do autoboxing if needed), than return right part (do autoboxing again if needed). In case of (1) it will print eq. In case of (2) - neq. I assumed scenario 2. // let's rewrite one in today-s java. public static void main(String[] args) { Map map = new HashMap(); // x[1]=128 Integer tmp=128; map.put(1,128); if (map.get(1)==tmp) { System.err.println("eq"); } else { System.err.println("neq"); } } But yes, we can force scenario 1, require in specification of assignment 1. if indexed setter call require autoboxing or integer type conversions - do one first and store in temporary variable 2. call setter with stored temporary variable (let call one boxedRight) 3. return boxedRight Then yes, scenario will be you: public static void main(String[] args) { Map map = new HashMap(); Integer tmp=128; map.put(1,tmp); if (map.get(1)==tmp) { System.err.println("eq"); } else { System.err.println("neq"); } } Wow - this is clear solution, which I miss ! From rssh at gradsoft.com.ua Thu Jun 25 18:13:00 2009 From: rssh at gradsoft.com.ua (Ruslan Shevchenko) Date: Fri, 26 Jun 2009 04:13:00 +0300 (EEST) Subject: indexed access: 10 ways to fix 'harmfull' issue In-Reply-To: <78d6653b10c8a550b8bb44fd38ab43ef.squirrel@wmail.gradsoft.ua> References: <51e42409ab3c01a7949f170020548431.squirrel@wmail.gradsoft.ua> <4A445B52.8000602@adres.pl> <78d6653b10c8a550b8bb44fd38ab43ef.squirrel@wmail.gradsoft.ua> Message-ID: And if we want allow programmer return result of assignment in own classes, that this rules must be applied if right part is collection, which are not implement additional 'getter/setter interfaces'. Also, statement that (7) will have same problems, as original (3) in my previous list is incorrect) (i. e. solution (7) also clear.) > require in specification of assignment > 1. if indexed setter call require autoboxing or integer type conversions > - > do one first and store in temporary variable > 2. call setter with stored temporary variable (let call one boxedRight) > 3. return boxedRight > From forax at univ-mlv.fr Fri Jun 26 02:25:23 2009 From: forax at univ-mlv.fr (=?ISO-8859-1?Q?R=E9mi_Forax?=) Date: Fri, 26 Jun 2009 11:25:23 +0200 Subject: Indexing access for Lists and Maps considered harmful? In-Reply-To: <15e8b9d20906240932m72a2748cyb683d1df0208fd08@mail.gmail.com> References: <36c722e00906231355v28598bc7kc12280275564bec1@mail.gmail.com> <17b2302a0906232040x4adf6894s55eab1d13e2c29a0@mail.gmail.com> <56B5CBBF-DEDA-4361-92CA-68B61AA60CEE@zwitserloot.com> <4A41DAED.6010903@optrak.co.uk> <07ba01c9f4a1$5b319d60$1194d820$@com> <4A421070.8030600@sun.com> <15e8b9d20906240812j40ad9ce4y14492e57a3f364f1@mail.gmail.com> <4A4247D1.70009@univ-mlv.fr> <15e8b9d20906240932m72a2748cyb683d1df0208fd08@mail.gmail.com> Message-ID: <4A449403.2070700@univ-mlv.fr> Neal Gafter a ?crit : > On Wed, Jun 24, 2009 at 8:35 AM, R?mi Forax > wrote: > > import static put symbol name is the scope, do you propose that > the compiler look for > any "operator_index_get" in the scope ? > > > As I said, this is not my preferred solution to this problem space, > but if you take this approach, then yes. Sorry, I think i've forget to read a mail, what is your preferred solution ? > > import static java.util.Collections.operator_index_get; > > class A { > List list; > > public int operator_index_get(Object o, int index) { > ... > return list[index]; > } > } > > How this example is translated by the compiler ? > > > The same way it translates any self-recursive method. Do you think it > likely that someone would accidentally write a method like that? > FindBugs will point out this problem. This is one of the reasons I > prefer an approach based on extension methods. I am not confident with the fact that operator overloading depends on what is currently in the scope. > > Morever with extension methods is that you loose the polymorphism : > > > I think you mean that the spec depends on ad-hoc polymorphism > (overloading) rather than subtype polymorphism (overriding). The > actual implementation of the operators, as I've shown, do indeed > depend on subtype polymorphism in precisely the same way as the > original proposal. The original proposal simply cannot be retrofitted > onto the interface Collection at all, and you've shown that this > proposal could (though your choice of implementation is problematic). > Just because you could doesn't mean you should. > This example is not artificial, So yes I could and I guess I will not be the only one to try. > Looking at it another way: this alternative encodes the meaning of the > index operators in external APIs, instead of hardcoding them in the > (external) JLS. APIs can be overloaded, and can be defined in terms > of methods that may be overridden. The JLS cannot be "overloaded" or > "overridden" at all. > That the strength of the extension methods. But I am not sure that static import is the good way to implement extension methods. static imported methods are not part of the interface of the class they augment so the semantics of an index operator can be different for different part of a program. I don't like that idea. R?mi From neal at gafter.com Fri Jun 26 08:31:55 2009 From: neal at gafter.com (Neal Gafter) Date: Fri, 26 Jun 2009 08:31:55 -0700 Subject: Indexing access for Lists and Maps considered harmful? In-Reply-To: <4A449403.2070700@univ-mlv.fr> References: <36c722e00906231355v28598bc7kc12280275564bec1@mail.gmail.com> <56B5CBBF-DEDA-4361-92CA-68B61AA60CEE@zwitserloot.com> <4A41DAED.6010903@optrak.co.uk> <07ba01c9f4a1$5b319d60$1194d820$@com> <4A421070.8030600@sun.com> <15e8b9d20906240812j40ad9ce4y14492e57a3f364f1@mail.gmail.com> <4A4247D1.70009@univ-mlv.fr> <15e8b9d20906240932m72a2748cyb683d1df0208fd08@mail.gmail.com> <4A449403.2070700@univ-mlv.fr> Message-ID: <15e8b9d20906260831o5e0e3bfat6828a695c26b187@mail.gmail.com> On Fri, Jun 26, 2009 at 2:25 AM, R?mi Forax wrote: > Neal Gafter a ?crit : > >> On Wed, Jun 24, 2009 at 8:35 AM, R?mi Forax > forax at univ-mlv.fr>> wrote: >> >> import static put symbol name is the scope, do you propose that >> the compiler look for >> any "operator_index_get" in the scope ? >> >> >> As I said, this is not my preferred solution to this problem space, but if >> you take this approach, then yes. >> > > Sorry, I think i've forget to read a mail, what is your preferred solution > ? My preferred solution is based on extension methods. The rewriting would then be from a[b] to a.operator_index_get(b), or something like that. This solution requires that the language designers think more than one step ahead: either add extension methods now or defer support for this feature until we add support for extension methods. The ARM proposal could similarly be vastly simplified and at the same time broadened in its ability to be retrofitted onto existing interfaces by the use of this technique. Generally speaking, to simplify the specification and simplify backward compatibility, there are a number of techniques that should be considered when making further changes to the language, including: (a) specification by syntactic transformation (a pattern-based approach); (b) extension methods (to make such specifications more broadly applicable and more flexibly used); and (c) and context-sensitive keywords. The alternatives (e.g. retrofitting new interfaces and reusing keywords) generally don't work out as well. You can approximate some of the benefits of extension methods by saying that only methods from the static import scope are considered when binding an indexing operation. From Dalibor.Topic at Sun.COM Fri Jun 26 15:47:59 2009 From: Dalibor.Topic at Sun.COM (Dalibor Topic) Date: Sat, 27 Jun 2009 00:47:59 +0200 Subject: Indexing access for Lists and Maps considered harmful? In-Reply-To: <4A425EEB.7010401@adres.pl> References: <4A425EEB.7010401@adres.pl> Message-ID: <4A45501F.7080606@sun.com> Artur Biesiadowski wrote: > Paul Benedict wrote: >> I am not a fan of this proposal in general. Two things to comment on: >> >> (1) Collections are located in java.util, but the JLS can only >> reference classes in java.lang, correct? If I have my facts correct >> (doubting), this enhancement would set a new precedent by having a >> language feature reach into a non-lang package. >> > Look at java.lang.Iterable. It was added to implement forach operator > and by that JLS indirectly references java.util.Iterator. > JLS 3 ?8.3.1.3 transient Fields references java.io.Serializable, for example. cheers, dalibor topic -- ******************************************************************* Dalibor Topic Tel: (+49 40) 23 646 738 Java F/OSS Ambassador AIM: robiladonaim Sun Microsystems GmbH Mobile: (+49 177) 2664 192 Nagelsweg 55 http://openjdk.java.net D-20097 Hamburg mailto:Dalibor.Topic at sun.com Sitz der Gesellschaft: Sonnenallee 1, D-85551 Kirchheim-Heimstetten Amtsgericht M?nchen: HRB 161028 Gesch?ftsf?hrer: Thomas Schr?der, Wolfgang Engels, Wolf Frenkel Vorsitzender des Aufsichtsrates: Martin H?ring From brucechapman at paradise.net.nz Mon Jun 29 02:12:52 2009 From: brucechapman at paradise.net.nz (Bruce Chapman) Date: Mon, 29 Jun 2009 21:12:52 +1200 Subject: Thoughts on unified integer literal improvements In-Reply-To: <4A1DC533.2060202@sun.com> References: <4A1DC533.2060202@sun.com> Message-ID: <4A488594.2010000@paradise.net.nz> Joe Darcy wrote: > Hello. > > On the set of improved integer literal features, I think combining the > underscores as separators and binary literals is straightforward given > separately correct grammars for each change. > > As an alternate to "y" and "s" suffices, I suggesting considering a > "u" suffix to mean unsigned. Literals with a trailing "u" would have > type int; widening conversions of such literals would 0 extend and > narrowing conversions would range check on the width of set bits. For > example, > All, I have spent some time considering Joe's suggestions. While I really like the aesthetics of "u" means "unsigned" compared with "y" suffix for "byte", I am also aware of the considerable extra complexity of defining a new primitive type in the JLS. From a first scan I have identified the most obvious change points which are recorded in the google document http://docs.google.com/View?id=dcvp3mkv_112567xb4n I have also made a (somewhat subjective) comparison of the "u" vs "y" proposals, along with a variation that combines the "u" suffix surface syntax with more the semantics of the previous autosizing proposal (which introduced a new Hex prefix) but done as a suffix in order to be applicable across all number bases. A comparison of those is available in the google document http://spreadsheets.google.com/ccc?key=rS9MTI5_fP9GwWrAafy_LwQ In practice both the unsigned int and autosizing suffixes behave almost identically, and where different can both be used to achieve the same goals with the following exception Autosizing cannot be used to declare a decimal between Integer.MAX_VALUE and twice that which zero extends to a long. The simple workaround is to use "L" suffix to force a long, which more correctly captures the design intent anyway. My preference at the moment is for the "u" suffix with autosizing semantics. Some work is needed to define the autosizing rules exactly - I am currently leaning toward (loosely) The type of the literal is the smallest integral type capable of holding all significant bits of the constant, unless the first digit of the literal (excluding prefix characters) is '0' in which case the type is the smallest integral type capable of holding one more than the number of significant bits of the constant value. eg 0xFFu is byte, 0x0FFu is short. However my goal is to write a proposal which allows "nice" hexadecimal byte literals with maximum its likelihood of selection for JDK7, and to that end, I'd appreciate comments, especially any that run counter to my following assumptions 1) "unsigned int" needs JLS changes that are excessive comparative to their value, when compared to the other options. 2) Having a new primitive type "unsigned int" which can only be used for literals, and cannot be used to declare variables has a high probability of being viewed negatively by the user community. Some users would wish for full unsigned support, and others would wish that it wasn't there at all. The effort cost of explaining this afterwards will be significant 3) Explicit use of leading '0' digit in autosizing case to force zero extension is a good thing. 4) One way to deal with the octal literal vs leading zero widens conflict would be to introduce alternate alphabetic prefixes for decimal (d) and octal (o) eg 0d10 (10) and 0o10 (8) which could be used in combination with a leading 0 digit to force zero extend (eg 0d0255u is short value 255)- however I assume this is unjustifiable complexity. And if you have been explicitly addressed in this email, I'd especially value your feedback. regards Bruce From Weijun.Wang at Sun.COM Mon Jun 29 02:56:53 2009 From: Weijun.Wang at Sun.COM (Weijun Wang) Date: Mon, 29 Jun 2009 17:56:53 +0800 Subject: Thoughts on unified integer literal improvements In-Reply-To: <4A1DC533.2060202@sun.com> References: <4A1DC533.2060202@sun.com> Message-ID: <4A488FE5.60309@sun.com> > long ell = 0xFFFFFFFFu; // A positive long value Any particular requirement here? Why not simply long ell = 0xFFFFFFFFl; > > I think this approach has some advantages over the "y" suffix; in > particular I think it gives more desirable behavior in cases like this: > > byte b = 0xFFy // a negative byte value > byte b = 0xFFu // also a negative byte value > > short s = 0xFFy // a negative short value, -128; > // byte value is signed extended > short s = 0xFFu // a positive short value, +127 > > int i = 0xFFy // -128 > int i = 0xFFu // 127 Does this mean the actual value of 0xFFu is determined by looking at the LHS of the assignment? This is terrible. I'd rather use something like 0bXX which is itself always a byte literal. Max > > -Joe > From reinier at zwitserloot.com Mon Jun 29 03:00:13 2009 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Mon, 29 Jun 2009 12:00:13 +0200 Subject: Thoughts on unified integer literal improvements In-Reply-To: <4A488FE5.60309@sun.com> References: <4A1DC533.2060202@sun.com> <4A488FE5.60309@sun.com> Message-ID: <09478A11-773E-4555-B2C8-199CB581E252@zwitserloot.com> 0xFFu is 127? I hope that was a typo and you meant to write 256. --Reinier Zwitserloot On 2009/29/06, at 11:56, Weijun Wang wrote: >> long ell = 0xFFFFFFFFu; // A positive long value > > Any particular requirement here? Why not simply > > long ell = 0xFFFFFFFFl; > >> >> I think this approach has some advantages over the "y" suffix; in >> particular I think it gives more desirable behavior in cases like >> this: >> >> byte b = 0xFFy // a negative byte value >> byte b = 0xFFu // also a negative byte value >> >> short s = 0xFFy // a negative short value, -128; >> // byte value is signed extended >> short s = 0xFFu // a positive short value, +127 >> >> int i = 0xFFy // -128 >> int i = 0xFFu // 127 > > Does this mean the actual value of 0xFFu is determined by looking at > the > LHS of the assignment? This is terrible. > > I'd rather use something like 0bXX which is itself always a byte > literal. > > Max > >> >> -Joe >> > From Weijun.Wang at Sun.COM Mon Jun 29 03:03:01 2009 From: Weijun.Wang at Sun.COM (Weijun Wang) Date: Mon, 29 Jun 2009 18:03:01 +0800 Subject: Thoughts on unified integer literal improvements In-Reply-To: <09478A11-773E-4555-B2C8-199CB581E252@zwitserloot.com> References: <4A1DC533.2060202@sun.com> <4A488FE5.60309@sun.com> <09478A11-773E-4555-B2C8-199CB581E252@zwitserloot.com> Message-ID: <4A489155.2020903@sun.com> 255 or -1. Reinier Zwitserloot wrote: > 0xFFu is 127? > > I hope that was a typo and you meant to write 256. > > --Reinier Zwitserloot > > > > On 2009/29/06, at 11:56, Weijun Wang wrote: > >>> long ell = 0xFFFFFFFFu; // A positive long value >> Any particular requirement here? Why not simply >> >> long ell = 0xFFFFFFFFl; >> >>> I think this approach has some advantages over the "y" suffix; in >>> particular I think it gives more desirable behavior in cases like >>> this: >>> >>> byte b = 0xFFy // a negative byte value >>> byte b = 0xFFu // also a negative byte value >>> >>> short s = 0xFFy // a negative short value, -128; >>> // byte value is signed extended >>> short s = 0xFFu // a positive short value, +127 >>> >>> int i = 0xFFy // -128 >>> int i = 0xFFu // 127 >> Does this mean the actual value of 0xFFu is determined by looking at >> the >> LHS of the assignment? This is terrible. >> >> I'd rather use something like 0bXX which is itself always a byte >> literal. >> >> Max >> >>> -Joe >>> > > From Alex.Buckley at Sun.COM Mon Jun 29 11:32:03 2009 From: Alex.Buckley at Sun.COM (Alex Buckley) Date: Mon, 29 Jun 2009 11:32:03 -0700 Subject: Thoughts on unified integer literal improvements In-Reply-To: <4A488594.2010000@paradise.net.nz> References: <4A1DC533.2060202@sun.com> <4A488594.2010000@paradise.net.nz> Message-ID: <4A4908A3.3020307@sun.com> Hi Bruce, Bruce Chapman wrote: > My preference at the moment is for the "u" suffix with autosizing > semantics. Just as well, since a new unsigned primitive type in the JLS is not on the table in Coin. > Some work is needed to define the autosizing rules exactly - I am > currently leaning toward (loosely) > > The type of the literal is the smallest integral type capable of > holding all significant bits of the constant, unless the first > digit of the literal (excluding prefix characters) is '0' in which > case the type is the smallest integral type capable of holding one more > than the number of significant bits of the constant value. eg 0xFFu is > byte, 0x0FFu is short. I personally tend to shy away from 'correct but clever' rules that make the reader work hard to follow the types. > 1) "unsigned int" needs JLS changes that are excessive comparative to > their value, when compared to the other options. > > 2) Having a new primitive type "unsigned int" which can only be used for > literals, and cannot be used to declare variables has a high probability > of being viewed negatively by the user community. Some users would wish > for full unsigned support, and others would wish that it wasn't there at > all. The effort cost of explaining this afterwards will be significant Thumbs up so far! > 3) Explicit use of leading '0' digit in autosizing case to force zero > extension is a good thing. > > 4) One way to deal with the octal literal vs leading zero widens > conflict would be to introduce alternate alphabetic prefixes for decimal > (d) and octal (o) eg 0d10 (10) and 0o10 (8) which could be used in > combination with a leading 0 digit to force zero extend (eg 0d0255u is > short value 255)- however I assume this is unjustifiable complexity. Unjustifiable, correct. Triggering autosizing with a leading 0 almost seems like a clash for the sake of it! Keep autosizing out unless experience with prototypes shows that the other integer literal improvements are worthless without it. Alex From brucechapman at paradise.net.nz Mon Jun 29 19:12:28 2009 From: brucechapman at paradise.net.nz (brucechapman at paradise.net.nz) Date: Tue, 30 Jun 2009 14:12:28 +1200 (NZST) Subject: Thoughts on unified integer literal improvements In-Reply-To: <4A4908A3.3020307@sun.com> References: <4A1DC533.2060202@sun.com> <4A488594.2010000@paradise.net.nz> <4A4908A3.3020307@sun.com> Message-ID: <1246327948.4a49748c319ae@www.paradise.net.nz> Quoting Alex Buckley : > Hi Bruce, > > Bruce Chapman wrote: > > My preference at the moment is for the "u" suffix with autosizing > > semantics. > > Just as well, since a new unsigned primitive type in the JLS is not on > the table in Coin. OK, that's a pretty clear indicator. > > > Some work is needed to define the autosizing rules exactly - I am > > currently leaning toward (loosely) > > > > The type of the literal is the smallest integral type capable of > > holding all significant bits of the constant, unless the first > > digit of the literal (excluding prefix characters) is '0' in which > > case the type is the smallest integral type capable of holding one > more > > than the number of significant bits of the constant value. eg 0xFFu is > > > byte, 0x0FFu is short. > > I personally tend to shy away from 'correct but clever' rules that make > > the reader work hard to follow the types. In the original autosizing which was just for hexadecimal, the size was specified based on the number of digits. When you extend it to decimal and octal as well, basing the size on number of digits gets real ugly, real fast. So "as small as possible" seems more natural. A leading zero digit forces zero extend by making it 1 bit bigger before determining the type, thereby ensuring a zero value high bit when the literal has a leading zero. That seems quite a natural thing to do as well. Obviously more work is needed on specifying that behaviour but I am still happy with the concept. I guess if the leading zero rule was dropped the only thing to be lost is the ability to create short literals less that 255. Thoughts? > > > 1) "unsigned int" needs JLS changes that are excessive comparative to > > > their value, when compared to the other options. > > > > 2) Having a new primitive type "unsigned int" which can only be used > for > > literals, and cannot be used to declare variables has a high > probability > > of being viewed negatively by the user community. Some users would > wish > > for full unsigned support, and others would wish that it wasn't there > at > > all. The effort cost of explaining this afterwards will be > significant > > Thumbs up so far! > > > 3) Explicit use of leading '0' digit in autosizing case to force zero > > > extension is a good thing. > > > > 4) One way to deal with the octal literal vs leading zero widens > > conflict would be to introduce alternate alphabetic prefixes for > decimal > > (d) and octal (o) eg 0d10 (10) and 0o10 (8) which could be used in > > combination with a leading 0 digit to force zero extend (eg 0d0255u is > > > short value 255)- however I assume this is unjustifiable complexity. > > Unjustifiable, correct. Triggering autosizing with a leading 0 almost > seems like a clash for the sake of it! Keep autosizing out unless > experience with prototypes shows that the other integer literal > improvements are worthless without it. The autosizing (if we pursue that) would be triggered by the "u" suffix, the leading zero would just ensure that the resulting literal had at least its most significant bit set to zero - therefore ensuring zero extend when widening - which approximates Joe's semantics without the special "unsigned int" type. Does that change your opinion on autosizing? > > Alex > Thanks for your comments Bruce From brucechapman at paradise.net.nz Mon Jun 29 19:25:00 2009 From: brucechapman at paradise.net.nz (brucechapman at paradise.net.nz) Date: Tue, 30 Jun 2009 14:25:00 +1200 (NZST) Subject: Thoughts on unified integer literal improvements In-Reply-To: <4A488FE5.60309@sun.com> References: <4A1DC533.2060202@sun.com> <4A488FE5.60309@sun.com> Message-ID: <1246328700.4a49777c21249@www.paradise.net.nz> Quoting Weijun Wang : > > long ell = 0xFFFFFFFFu; // A positive long value > > Any particular requirement here? Why not simply > > long ell = 0xFFFFFFFFl; > > > > > I think this approach has some advantages over the "y" suffix; in > > particular I think it gives more desirable behavior in cases like > this: > > > > byte b = 0xFFy // a negative byte value > > byte b = 0xFFu // also a negative byte value > > > > short s = 0xFFy // a negative short value, -128; > > // byte value is signed extended > > short s = 0xFFu // a positive short value, +127 > > > > int i = 0xFFy // -128 > > int i = 0xFFu // 127 > > Does this mean the actual value of 0xFFu is determined by looking at > the > LHS of the assignment? This is terrible. Yes that would be terrible if it were true, fortunately it is not. The value is determined by the digits and any radix specified by the prefix. In the above examples, the "y" suffix means byte, so when is widened to a short or int it sign extends and stays negative. The "u" suffix would create a special type that would always zero extend when widening giving a positive number. > > I'd rather use something like 0bXX which is itself always a byte > literal. But that is inconsistent, prefixes currently determine radix, suffixes determine type. Also the binary literals part of the proposal is using 0b as a prefix for binary literals so 0bXX is an int. Bruce > > Max > > > > > -Joe > > > > From Weijun.Wang at Sun.COM Mon Jun 29 19:39:38 2009 From: Weijun.Wang at Sun.COM (Weijun Wang) Date: Tue, 30 Jun 2009 10:39:38 +0800 Subject: Thoughts on unified integer literal improvements In-Reply-To: <1246328700.4a49777c21249@www.paradise.net.nz> References: <4A1DC533.2060202@sun.com> <4A488FE5.60309@sun.com> <1246328700.4a49777c21249@www.paradise.net.nz> Message-ID: <4A497AEA.5090803@sun.com> brucechapman at paradise.net.nz wrote: > Quoting Weijun Wang : > >>> long ell = 0xFFFFFFFFu; // A positive long value >> Any particular requirement here? Why not simply >> >> long ell = 0xFFFFFFFFl; >> >>> I think this approach has some advantages over the "y" suffix; in >>> particular I think it gives more desirable behavior in cases like >> this: >>> byte b = 0xFFy // a negative byte value >>> byte b = 0xFFu // also a negative byte value >>> >>> short s = 0xFFy // a negative short value, -128; >>> // byte value is signed extended >>> short s = 0xFFu // a positive short value, +127 >>> >>> int i = 0xFFy // -128 >>> int i = 0xFFu // 127 >> Does this mean the actual value of 0xFFu is determined by looking at >> the >> LHS of the assignment? This is terrible. > > Yes that would be terrible if it were true, fortunately it is not. The value is > determined by the digits and any radix specified by the prefix. In the above > examples, the "y" suffix means byte, so when is widened to a short or int it > sign extends and stays negative. The "u" suffix would create a special type that > would always zero extend when widening giving a positive number. I still find it difficult to understand this 'u' thing. When you say "zero extend when", isn't that the same with what I said "depending on the LHS"? What is the most important usage of it? > >> I'd rather use something like 0bXX which is itself always a byte >> literal. > > But that is inconsistent, prefixes currently determine radix, suffixes determine > type. Also the binary literals part of the proposal is using 0b as a prefix for > binary literals so 0bXX is an int. I see. Thanks Max > > Bruce > >> Max >> >>> -Joe >>> >> > From Weijun.Wang at Sun.COM Tue Jun 30 00:00:27 2009 From: Weijun.Wang at Sun.COM (Weijun Wang) Date: Tue, 30 Jun 2009 15:00:27 +0800 Subject: Thoughts on unified integer literal improvements In-Reply-To: <4A49AF0E.3010202@paradise.net.nz> References: <4A1DC533.2060202@sun.com> <4A488FE5.60309@sun.com> <1246328700.4a49777c21249@www.paradise.net.nz> <4A497AEA.5090803@sun.com> <4A49AF0E.3010202@paradise.net.nz> Message-ID: <4A49B80B.3080704@sun.com> Bruce Chapman wrote: > Weijun Wang wrote: >> brucechapman at paradise.net.nz wrote: >> >>> Quoting Weijun Wang : >>> >>> >>>>> long ell = 0xFFFFFFFFu; // A positive long value >>>>> >>>> Any particular requirement here? Why not simply >>>> >>>> long ell = 0xFFFFFFFFl; >>>> >>>> >>>>> I think this approach has some advantages over the "y" suffix; in >>>>> particular I think it gives more desirable behavior in cases like >>>>> >>>> this: >>>> >>>>> byte b = 0xFFy // a negative byte value >>>>> byte b = 0xFFu // also a negative byte value >>>>> >>>>> short s = 0xFFy // a negative short value, -128; >>>>> // byte value is signed extended >>>>> short s = 0xFFu // a positive short value, +127 >>>>> >>>>> int i = 0xFFy // -128 >>>>> int i = 0xFFu // 127 >>>>> >>>> Does this mean the actual value of 0xFFu is determined by looking at >>>> the >>>> LHS of the assignment? This is terrible. >>>> >>> Yes that would be terrible if it were true, fortunately it is not. The value is >>> determined by the digits and any radix specified by the prefix. In the above >>> examples, the "y" suffix means byte, so when is widened to a short or int it >>> sign extends and stays negative. The "u" suffix would create a special type that >>> would always zero extend when widening giving a positive number. >>> >> >> I still find it difficult to understand this 'u' thing. When you say >> "zero extend when", isn't that the same with what I said "depending on >> the LHS"? >> > > No, The JLS defines a number of conversions, one of which is widening > and when that occurs. For example > > byte b = 1; > > int j = b+1; > > in the second line the type of the expression "b+1" is not determined by > the LHS, but the various conversion rules say that the b expression of > type byte must be widened to an int before the addition and assignment > occur in that order. > > > Similarly when we say > > short s = 0xFFu; > > What is happening is that the type of the expression on the right has > some conversions applied before the assignment. Collectively those are > called assignment conversion, and when 0xFFu has a type of byte, then > the particular assignment conversion which is applied is the widening > conversion. I somehow understand your point. This 0xFFu is a brand new data type. Don't know if it can be coined without any new VM bytecode. Implementing it with some syntactic sugar might bring unexpected troubles. What does f(0xFFu) mean when there are both f(byte) and f(int)? > > In practice many operations involving byte or short literals will see > them widened to int first, which gets to your next question >> What is the most important usage of it? >> > byte b = 0xFF; > > currently fails because 0xFF is an int and when we assign that to a > byte, we find that the value (255) is out of range for byte (-128 - 127) > and the compiler knows this and won't let us do it. We could write > > byte b = (byte)0xFF; But you already have byte b = 0xFFy; > > but that gets ugly because sometimes the bit pattern does fit and the > cast is unnecessary. > > By being able to encode byte literals code which is manipulating then > becomes less cluttered. > > Here is a (slightly contrived for simplification) example showing how > the sign extension can be confusing. > > int i = (byte)0xFF; If I really write this way, I would use 0xFFFFFFFF. If I want 255, I would write 0xFF. Thanks Max > > now you might think that "i" has a value 255, but in fact it has a value > of -1, because the byte has a value of -1. Joe's proposal was a means > to prevent these non obvious sign extension situations. > > Bruce > >> >>>> I'd rather use something like 0bXX which is itself always a byte >>>> literal. >>>> >>> But that is inconsistent, prefixes currently determine radix, suffixes determine >>> type. Also the binary literals part of the proposal is using 0b as a prefix for >>> binary literals so 0bXX is an int. >>> >> >> I see. >> >> Thanks >> Max >> >> >>> Bruce >>> >>> >>>> Max >>>> >>>> >>>>> -Joe >>>>> >>>>> >>>> >>>> >> >> > From Weijun.Wang at Sun.COM Tue Jun 30 03:47:18 2009 From: Weijun.Wang at Sun.COM (Max (Weijun) Wang) Date: Tue, 30 Jun 2009 18:47:18 +0800 Subject: Thoughts on unified integer literal improvements In-Reply-To: <4A49D7B8.8060104@paradise.net.nz> References: <4A1DC533.2060202@sun.com> <4A488FE5.60309@sun.com> <1246328700.4a49777c21249@www.paradise.net.nz> <4A497AEA.5090803@sun.com> <4A49AF0E.3010202@paradise.net.nz> <4A49B80B.3080704@sun.com> <4A49D7B8.8060104@paradise.net.nz> Message-ID: <4BA7F830-DC6F-417D-B0F9-37968D25AC02@Sun.COM> On Jun 30, 2009, at 5:15 PM, Bruce Chapman wrote: > >>> What is happening is that the type of the expression on the right >>> has >>> some conversions applied before the assignment. Collectively those >>> are >>> called assignment conversion, and when 0xFFu has a type of byte, >>> then >>> the particular assignment conversion which is applied is the >>> widening >>> conversion. >>> >> >> I somehow understand your point. This 0xFFu is a brand new data type. >> > Almost - If its Joe's 0xFFu then yes, but that has been determined > too big for coin, if it's autosizing then no, its not a new type, > just a new literal syntax for a literal whose type depends on the > literal value, but those possible types are existing types. "a new literal syntax for a literal whose type depends on the literal value". So, 0xFFu, being two bytes long, is always a byte? Then what does this line mean? >>>> int i = 0xFFu // 127 (should be 255) Or is this only Joe's 0xFFu? Your i will be -1? >> Don't know if it can be coined without any new VM bytecode. >> Implementing >> it with some syntactic sugar might bring unexpected troubles. >> > No new VM support required, just some (quite minor) changes to the > compiler. Getting the spec right is probably more effort than > getting the compile code written. >> What does f(0xFFu) mean when there are both f(byte) and f(int)? >> >> > The same as f((byte)255) > >>> In practice many operations involving byte or short literals will >>> see >>> them widened to int first, which gets to your next question >>> >>>> What is the most important usage of it? >>>> >>>> >>> byte b = 0xFF; >>> >>> currently fails because 0xFF is an int and when we assign that to a >>> byte, we find that the value (255) is out of range for byte (-128 >>> - 127) >>> and the compiler knows this and won't let us do it. We could write >>> >>> byte b = (byte)0xFF; >>> >> >> But you already have >> >> byte b = 0xFFy; >> >> > 0xFFy and 0xFFu are alternative designs being explored, they won't > BOTH happen, hopefully one will. Got it. I would prefer 0xFFy. How about a step further like -- byte[] bs = 0x0102030405060708AABBCCDDEEFFy; > >>> but that gets ugly because sometimes the bit pattern does fit and >>> the >>> cast is unnecessary. >>> >>> By being able to encode byte literals code which is manipulating >>> then >>> becomes less cluttered. >>> >>> Here is a (slightly contrived for simplification) example showing >>> how >>> the sign extension can be confusing. >>> >>> int i = (byte)0xFF; >>> >> >> If I really write this way, I would use 0xFFFFFFFF. If I want 255, I >> would write 0xFF. >> >> > The problem is not when you want the sign extension to happen, the > problem is when it happens when you don't expect it. When what you > really want (in the example) is for the int to have a value 0xFF. > The example doesn't show it well, but the sign extend on widening > can quite easily catch you out. I have been writing code doing low > level protocol byte munging stuff for years, Me too, http://hg.openjdk.java.net/jdk7/tl/jdk/rev/7360321c37e3 Thanks Max > and I thought I understood it. It wasn't till I started > investigating this area for project coin that I really understood it > (although even that is a bit of a exageration) I thought I > understood, but in hindsight I just knew a few magic spells that > gave the right answers. I was constantly seeing surprises and common > mistakes in code I and colleagues were writing. The coin proposals > are aimed at addresses the worst of these pitfalls. > > Bruce > >> Thanks >> Max >> >> > From abies at adres.pl Tue Jun 30 04:05:59 2009 From: abies at adres.pl (abies at adres.pl) Date: Tue, 30 Jun 2009 13:05:59 +0200 Subject: Thoughts on unified integer literal improvements In-Reply-To: 4BA7F830-DC6F-417D-B0F9-37968D25AC02@Sun.COM Message-ID: "Max (Weijun) Wang" napisa?(a): > How about a step further like -- > > byte[] bs = 0x0102030405060708AABBCCDDEEFFy; > Which direction it would be read? byte[0] is 0x01 or 0x0FF ? What with byte[] bs = 0xabcy; ? Would it be legal - and would it be equivalent to 0x0abcy, 0xa0bcy, 0xabc0y ? I understand that it would be kind of byte[] literal, so no possibility of overwriting contents of existing byte array, short of using System.arraycopy(0x0102030405060708AABBCCDDEEFFy,0,bs,0,14); ? Regards, Artur From Weijun.Wang at Sun.COM Tue Jun 30 04:13:56 2009 From: Weijun.Wang at Sun.COM (Max (Weijun) Wang) Date: Tue, 30 Jun 2009 19:13:56 +0800 Subject: Thoughts on unified integer literal improvements In-Reply-To: References: Message-ID: On Jun 30, 2009, at 7:05 PM, abies at adres.pl wrote: > > > "Max (Weijun) Wang" napisa?(a): > >> How about a step further like -- >> >> byte[] bs = 0x0102030405060708AABBCCDDEEFFy; >> > > Which direction it would be read? byte[0] is 0x01 or 0x0FF ? 0x01 > > What with byte[] bs = 0xabcy; ? Would it be legal - and would it be > equivalent to 0x0abcy, 0xa0bcy, 0xabc0y ? Illegal. In fact, byte b = 0x1y; // maybe illegal. byte[] b = 0xABy; // illegal. The array literal must be at least length 2. Max > > I understand that it would be kind of byte[] literal, so no > possibility of overwriting contents of existing byte array, short of > using > System.arraycopy(0x0102030405060708AABBCCDDEEFFy,0,bs,0,14); > ? > > > Regards, > Artur From reinier at zwitserloot.com Tue Jun 30 04:36:24 2009 From: reinier at zwitserloot.com (Reinier Zwitserloot) Date: Tue, 30 Jun 2009 13:36:24 +0200 Subject: Thoughts on unified integer literal improvements In-Reply-To: References: Message-ID: <092FDA2C-172D-41E2-B857-C335F03EC4E7@zwitserloot.com> I don't think Artur's issues are particularly tough nuts to crack (in that they have an easy and obvious right answer - see end of this post), but I do have some rather serious reservations about this byte array literal syntax: 1) Is this a context-sensitive literal? In other words, what would: byte[] bs = 0x01y; do? or: byte b = 0x0102y? or: void method(byte b) {} void method(byte[] bs) {} method(0x001y); do? Because that's quite a step, and context-sensitive (e.g. depending on the LHS) literals have been mentioned before as iffy. I'm not as opposed to context sensitive literals as others on this list, but it is nevertheless an important distinction. So, presuming for a moment these ARENT context-sensitive, then: 2) Isn't this rather inconsistent? 0x01y is a byte, but 0x0102y is a byte array. What if I want a 1-length byte array? Should byte literals auto-cast themselves into array form on an as needed basis (autoboxing/ unboxing is different from being context-sensitive, though auto- conversion has its own troubles). Is just a lone '0xy' a zero-length byte array? What about 0 padding? Do those count? Is 0x000102y a size-2 or a size-3 byte array? 3) Where does it end? Can I make int arrays? Will this be available if 0b10111001 style binary literals become standard java? Should decimal literals pack into an array like this? The amount of slots required for a given decimal is non-obvious, so is that a good idea (certainly not if slot size determines if its an array literal or a primitive!)? But if not, is this consistent? 4) Weren't we trying to move *AWAY* from arrays? Scala and other languages show that it is basically possible to eliminate primitives and smartly compile, via duplication for each primitive for example, code that is just as fast. Combine such a concept with reification, and byte[] is just an obsolete version of List. This is a very long way away, but we're nevertheless stuck with the unfortunate situation that generics and arrays don't play nicely with each other. 5) Where does it end part 2: If byte arrays are 'special' enough that it warrants ltierals, can regexp expressions box to Pattern objects, or, better yet, can I make actual Pattern literals? Compiling regexes is pricey, and with regexp literals you could do some syntax checking on them, so it's not just 'saving some characters'. How about XML strings? Aren't map and list literals ***FAR*** more useful than byte array literals? Seriously - where does it end? I'd love a proposal for some sort of library literal system, whereby, apt-processor-like, a certain format of literal results in a classpath check (via ServiceLoader) for some code that knows how to turn the stated literal into a primitive object; something java core knows, like an actual byte array literal of the type: new byte[] { 0x01, 0x02, 0x03 }; for example. A complete proposal for such a system is well beyond coin's scope, and there are some significant issues you'd have to resolve (one involves escaping: If you can stuff any characters inside a literal definition, how does the java parser know where it ends? Imagine a regexp literal that is delimited by / as is common in other languages - how would the parser know to treat any commas, closing parens, even newlines and string quotes inside the slashes as NOT closing the literal? On 2009/30/06, at 13:05, abies at adres.pl wrote: >> byte[] bs = 0x0102030405060708AABBCCDDEEFFy; >> > > Which direction it would be read? byte[0] is 0x01 or 0x0FF ? > EVERYTHING in java, where you have to choose between Big-Endian and Little-Endian, is Big-Endian. So, this one is easy and should not count against the proposal: byte[0] is 0x01. > What with byte[] bs = 0xabcy; ? Would it be legal - and would it be > equivalent to 0x0abcy, 0xa0bcy, 0xabc0y ? When in doubt, choose not legal. It's a lot easier for somebody to clarify by typing a single extra character (a 0) immediately as he writes it (provided a cool enough IDE that red-underlines the problem), then letting the user assume one way or another and spend an hour chasing bugs. Also not a strike against the proposal, presuming for a moment that you must have an even number of nibbles in this usage. > > > I understand that it would be kind of byte[] literal, so no > possibility of overwriting contents of existing byte array, short of > using > System.arraycopy(0x0102030405060708AABBCCDDEEFFy,0,bs,0,14); > ? > > > Regards, > Artur >