From lovro.pandzic at gmail.com Mon Dec 1 19:02:58 2014 From: lovro.pandzic at gmail.com (Lovro Pandzic) Date: Mon, 1 Dec 2014 20:02:58 +0100 Subject: Value types and parameter names Message-ID: Hello all, I've been monitoring the Valhalla project for some time now and I have a question: will the new parameter names API introduced in Java 8 be available for value types? If so, is there a possibility for it to be turned on by default? One great thing I like about the new parameter names is that it provides a supported way for eliminating the need of JavaBeans setters. See [1] for example. In various libraries and frameworks, setters are often used as a tool for both discovering component names of an object and for injecting those components while constructing it because parameter names of constructors were not available through reflection, at least not until Java 8. This approach goes against simplicity, immutability and only presents boilerplate in the code. Luckily, value types are planned to be immutable so setters are impossible. On the other hand, without setters, the only way for constructing those value types in those frameworks would be to use those constructor if they have parameter names available at runtime. [1] https://github.com/FasterXML/jackson-module-parameter-names Kind Regards, Lovro Pandzic From brian.goetz at oracle.com Mon Dec 1 19:18:15 2014 From: brian.goetz at oracle.com (Brian Goetz) Date: Mon, 01 Dec 2014 14:18:15 -0500 Subject: Value types and parameter names In-Reply-To: References: Message-ID: <547CBEF7.4050606@oracle.com> This is two separate questions, with one answer: Q: Would parameter names be available for value types? A: I see no reason why the answer for this should be any different than for reference classes. Q: Could it be turned on by default? A: I see no reason why the answer for this should be any different than for reference classes. In both cases, there's nothing special about value types that should interact with parameter names in any non-obvious way; doing otherwise would just introduce needless complexity. Value types are defined by classes just as reference types are, can have methods just like reference types do, and the treatment of parameter names in methods of value types should be identical to those of reference types. Now, maybe what you really are getting at is that you're asking to revisit the "why were they not turned on by default" decision (which was a complex decision that involved balancing multiple considerations)? On 12/1/2014 2:02 PM, Lovro Pandzic wrote: > Hello all, > > I've been monitoring the Valhalla project for some time now and I have a > question: will the new parameter names API introduced in Java 8 be > available for value types? If so, is there a possibility for it to be > turned on by default? > > One great thing I like about the new parameter names is that it provides a > supported way for eliminating the need of JavaBeans setters. See [1] for > example. In various libraries and frameworks, setters are often used as a > tool for both discovering component names of an object and for injecting > those components while constructing it because parameter names of > constructors were not available through reflection, at least not until Java > 8. This approach goes against simplicity, immutability and only presents > boilerplate in the code. Luckily, value types are planned to be immutable > so setters are impossible. > On the other hand, without setters, the only way for constructing those > value types in those frameworks would be to use those constructor if they > have parameter names available at runtime. > > [1] https://github.com/FasterXML/jackson-module-parameter-names > > Kind Regards, > Lovro Pandzic > From maurizio.cimadamore at oracle.com Fri Dec 5 12:32:01 2014 From: maurizio.cimadamore at oracle.com (maurizio.cimadamore at oracle.com) Date: Fri, 05 Dec 2014 12:32:01 +0000 Subject: hg: valhalla/valhalla/langtools: Fix bug with missing bytecode mapping on synthetic cast in return type. Message-ID: <201412051232.sB5CW1ip018417@aojmv0008> Changeset: 1030cc00b088 Author: mcimadamore Date: 2014-12-05 12:27 +0000 URL: http://hg.openjdk.java.net/valhalla/valhalla/langtools/rev/1030cc00b088 Fix bug with missing bytecode mapping on synthetic cast in return type. ! src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransTypes.java + test/tools/javac/valhalla/typespec/items/tests/TestGeneric2GenericCall.java From brian.goetz at oracle.com Sat Dec 6 00:48:51 2014 From: brian.goetz at oracle.com (brian.goetz at oracle.com) Date: Sat, 06 Dec 2014 00:48:51 +0000 Subject: hg: valhalla/valhalla/langtools: Add instantiated type of receiver to indy bootstrap arg list for invocation of generic methods Message-ID: <201412060048.sB60mpWH002957@aojmv0008> Changeset: 23b31119db0f Author: mcimadamore Date: 2014-12-05 19:48 -0500 URL: http://hg.openjdk.java.net/valhalla/valhalla/langtools/rev/23b31119db0f Add instantiated type of receiver to indy bootstrap arg list for invocation of generic methods ! src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java ! src/jdk.compiler/share/classes/com/sun/tools/javac/comp/SpecializeTypes.java ! src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Items.java From brian.goetz at oracle.com Sat Dec 6 00:50:03 2014 From: brian.goetz at oracle.com (brian.goetz at oracle.com) Date: Sat, 06 Dec 2014 00:50:03 +0000 Subject: hg: valhalla/valhalla/jdk: Adjust to new generic method argument format; now handling some forms of specialization of generic instance methods Message-ID: <201412060050.sB60o3Gu003274@aojmv0008> Changeset: bba8c0e79d80 Author: briangoetz Date: 2014-12-05 19:49 -0500 URL: http://hg.openjdk.java.net/valhalla/valhalla/jdk/rev/bba8c0e79d80 Adjust to new generic method argument format; now handling some forms of specialization of generic instance methods ! src/java.base/share/classes/java/lang/invoke/GenericMethodSpecializer.java ! src/java.base/share/classes/java/net/URLClassLoader.java ! src/java.base/share/classes/valhalla/specializer/SignatureSpecializer.java ! src/java.base/share/classes/valhalla/specializer/Specialize.java ! src/java.base/share/classes/valhalla/specializer/Specializer.java ! test/valhalla/test/valhalla/specializer/Box.java ! test/valhalla/test/valhalla/specializer/GenericMethodsTest.java ! test/valhalla/test/valhalla/specializer/TwoBox.java ! test/valhalla/test/valhalla/specializer/TwoBoxTest.java From brian.goetz at oracle.com Sat Dec 6 02:14:13 2014 From: brian.goetz at oracle.com (brian.goetz at oracle.com) Date: Sat, 06 Dec 2014 02:14:13 +0000 Subject: hg: valhalla/valhalla/jdk: More bugfixes in generic method handling Message-ID: <201412060214.sB62EDdE017677@aojmv0008> Changeset: 8597395ec187 Author: briangoetz Date: 2014-12-05 21:14 -0500 URL: http://hg.openjdk.java.net/valhalla/valhalla/jdk/rev/8597395ec187 More bugfixes in generic method handling ! src/java.base/share/classes/java/lang/invoke/GenericMethodSpecializer.java ! src/java.base/share/classes/valhalla/specializer/SignatureSpecializer.java ! src/java.base/share/classes/valhalla/specializer/Specializer.java ! test/valhalla/test/valhalla/specializer/TwoBoxTest.java From lovro.pandzic at gmail.com Sat Dec 6 23:04:34 2014 From: lovro.pandzic at gmail.com (Lovro Pandzic) Date: Sun, 7 Dec 2014 00:04:34 +0100 Subject: Value types and parameter names In-Reply-To: <547CBEF7.4050606@oracle.com> References: <547CBEF7.4050606@oracle.com> Message-ID: Well I do understand the reasoning behind it so I guess no value would be gained by changing the behavior for value classes. On the side note, is there an option to get classes with the JDK with parameter names? (like String, Integer, etc) On Mon, Dec 1, 2014 at 8:18 PM, Brian Goetz wrote: > This is two separate questions, with one answer: > > Q: Would parameter names be available for value types? > A: I see no reason why the answer for this should be any different than > for reference classes. > > Q: Could it be turned on by default? > A: I see no reason why the answer for this should be any different than > for reference classes. > > In both cases, there's nothing special about value types that should > interact with parameter names in any non-obvious way; doing otherwise would > just introduce needless complexity. Value types are defined by classes > just as reference types are, can have methods just like reference types do, > and the treatment of parameter names in methods of value types should be > identical to those of reference types. > > Now, maybe what you really are getting at is that you're asking to revisit > the "why were they not turned on by default" decision (which was a complex > decision that involved balancing multiple considerations)? > > > > > > > On 12/1/2014 2:02 PM, Lovro Pandzic wrote: > >> Hello all, >> >> I've been monitoring the Valhalla project for some time now and I have a >> question: will the new parameter names API introduced in Java 8 be >> available for value types? If so, is there a possibility for it to be >> turned on by default? >> >> One great thing I like about the new parameter names is that it provides a >> supported way for eliminating the need of JavaBeans setters. See [1] for >> example. In various libraries and frameworks, setters are often used as a >> tool for both discovering component names of an object and for injecting >> those components while constructing it because parameter names of >> constructors were not available through reflection, at least not until >> Java >> 8. This approach goes against simplicity, immutability and only presents >> boilerplate in the code. Luckily, value types are planned to be immutable >> so setters are impossible. >> On the other hand, without setters, the only way for constructing those >> value types in those frameworks would be to use those constructor if they >> have parameter names available at runtime. >> >> [1] https://github.com/FasterXML/jackson-module-parameter-names >> >> Kind Regards, >> Lovro Pandzic >> >> From john.r.rose at oracle.com Sun Dec 7 09:30:48 2014 From: john.r.rose at oracle.com (John Rose) Date: Sun, 7 Dec 2014 01:30:48 -0800 Subject: Value types and parameter names In-Reply-To: References: Message-ID: On Dec 1, 2014, at 11:02 AM, Lovro Pandzic wrote: > > On the other hand, without setters, the only way for constructing those > value types in those frameworks would be to use those constructor if they > have parameter names available at runtime. The counterpart of a "setFoo" method for an immutable class would be "withFoo": final __ByValue class Point { public final int x, y; public Point(int x, int y) { this.x = x; this.y = y; } public Point withX(int x1) { return new Point(x1, y); } public Point withY(int y1) { return new Point(x, y1); } } I think the same clunky tricks as can be done for "setters" can also be done for "with-ers". (Word note: "wither" has unpleasant connotations compared to "setter". A setter is a nice dog, a wether is a sad goat.) The awkwardness of working with "with-er" methods is well-known. For example, in a paper I was just browsing: > Abrahams: I've done a fair amount of programming in LISP, and there is one situation which I feel is symptomatic of the times when you really do want an imperative language. It is a situation that arises if you are planning to do programming in pure Lisp and you find that your functions accumulate a large number of arguments. [1] This often happens when you have a nmnber of variables and you are actually going through a process and at each stage of the process you want to change the state of the world a little bit--say, to change one of these variables. So you have the choice of either trying to communicate them all, or trying to do some sort of essentially imperative action that changes one of them. [2] If you try to list all of the transitions from state to state and incorporate them into one function, you'll find that this is not really a very natural kind of function because the natures of the transitions are too different. [3] [Landin, "The Next 700 Languages", CACM, March, 1966] [1]: Or, in 2014, Java value types with many fields. [2]: Perhaps with an auxiliary Java builder class. [3]: Result: Lots of little boilerplate Java functions, or use one class but cope with non-final fields. He's talking about LISP and the difficulty of updating one variable in a coordinated group of several; he wants a notation for changing the variable without getting fouled by side effects. I imagine him thinking back then, "we will surely figure this out soon enough". He is feeling after an imperative way of expressing a declarative result, and noticing that expressing all possible state transitions as separate functions is unnaturally verbose, just as in the case of withX/withY. Apparently we are still figuring this out, although more options have been put on the table in the last half century. The "do" blocks of Haskell show one way to bridge the gap between imperative and declarative. To get this right in Java might require doing some similar trick, but within the native Java "worldview" of classes and "culture" of safe coding. (As an escape hatch, Java has annotation-driven method generators and Lisp has macros. I'd prefer to avoid those when possible.) ? John From maurizio.cimadamore at oracle.com Wed Dec 10 16:42:29 2014 From: maurizio.cimadamore at oracle.com (maurizio.cimadamore at oracle.com) Date: Wed, 10 Dec 2014 16:42:29 +0000 Subject: hg: valhalla/valhalla/langtools: Improvements to type specialization pipeline: Message-ID: <201412101642.sBAGgUD7010966@aojmv0008> Changeset: 4f830f22c29c Author: mcimadamore Date: 2014-12-10 16:41 +0000 URL: http://hg.openjdk.java.net/valhalla/valhalla/langtools/rev/4f830f22c29c Improvements to type specialization pipeline: * redefine erasure in terms of specialized classes * avoid tweaking symbol types at specialization time (leading to compilation order issues) * logic to force specialization of supertypes before subtypes no longer required * add better support for specialized symbols so that they can flow through compilation pipeline w/o requiring code changes (i.e. remove specialize/unspecialize explicit calls) * misc cleanups ! src/jdk.compiler/share/classes/com/sun/tools/javac/code/Flags.java ! src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java ! src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java ! src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java ! src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java ! src/jdk.compiler/share/classes/com/sun/tools/javac/comp/SpecializeTypes.java ! src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransTypes.java ! src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java ! src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Items.java ! src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Pool.java + test/tools/javac/valhalla/typespec/Auxiliary04.java From tomas.mikula at gmail.com Tue Dec 16 02:41:58 2014 From: tomas.mikula at gmail.com (Tomas Mikula) Date: Tue, 16 Dec 2014 03:41:58 +0100 Subject: Conditional methods "for free" Message-ID: On Sep 30, 2014, at 8:10 AM, Simon Ochsenreither wrote: > There was a short mention of "conditional methods", e.g. enabling > methods only for a subset of some generic type. I don't know where conditional methods were mentioned and what their current state is (any links?), but here is an idea how to get conditional methods "for free" on top of two other (missing) features, which would both be useful independently in their own right. The first feature is lower bounds on type parameters, i.e. , as in class Optional { public Optional or(Optional other); } The other one is to allow multiple type paramater bounds, even if one of the bounds is itself a type variable. That is, allow bounds like or . I have no idea how technically feasible these features are, but I have encountered use cases for both of them. Once we have lower bounds and multiple bounds, we can express conditional methods like this: class Optional { default int getAsInt() { I value = get(); return value.intValue(); } } Valid substitute for I exists only when T extends Integer, thus the getAsInt() method can effectively be invoked only on Optional. Regards, Tomas From ali.ebrahimi1781 at gmail.com Tue Dec 16 08:28:35 2014 From: ali.ebrahimi1781 at gmail.com (Ali Ebrahimi) Date: Tue, 16 Dec 2014 11:58:35 +0330 Subject: Conditional methods "for free" In-Reply-To: References: Message-ID: see http://mail.openjdk.java.net/pipermail/lambda-dev/2010-November/002646.html for history. On Tue, Dec 16, 2014 at 6:11 AM, Tomas Mikula wrote: > > On Sep 30, 2014, at 8:10 AM, Simon Ochsenreither ochsenreither.de> wrote: > > > There was a short mention of "conditional methods", e.g. enabling > > methods only for a subset of some generic type. > > I don't know where conditional methods were mentioned and what their > current state is (any links?), but here is an idea how to get > conditional methods "for free" on top of two other (missing) features, > which would both be useful independently in their own right. > > The first feature is lower bounds on type parameters, i.e. , as > in > > class Optional { > public Optional or(Optional other); > } > > The other one is to allow multiple type paramater bounds, even if one > of the bounds is itself a type variable. That is, allow bounds like extends T & Foo> or . > > I have no idea how technically feasible these features are, but I have > encountered use cases for both of them. > > Once we have lower bounds and multiple bounds, we can express > conditional methods like this: > > class Optional { > default int getAsInt() { > I value = get(); > return value.intValue(); > } > } > > Valid substitute for I exists only when T extends Integer, thus the > getAsInt() method can effectively be invoked only on > Optional. > > Regards, > Tomas > From maurizio.cimadamore at oracle.com Tue Dec 16 11:22:15 2014 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Tue, 16 Dec 2014 11:22:15 +0000 Subject: Conditional methods "for free" In-Reply-To: References: Message-ID: <549015E7.3000203@oracle.com> This is indeed a clever way to restrict applicability of certain methods to specific receivers. However, applicability is only half of the story here; the other half is membership. In your proposed solution, 'or' will be a member of Optional - regardless of the parameterization of the generic class. It seems likely that the feature we are after (not saying we have yet arrived to a full solution here) will also restrict membership - i.e. 'or' will simply not exist on an Optional (and then applicability would of course follow). When migrating legacy, erasure-based code, it is in fact fairly common to end up with cases in which existing methods (Collection.remove(Object) anyone?) no longer make sense in a fully any-fied world - and it is likely we will need a way that to say that those method are only members of certain receivers but not others. That said, stay tuned, as you'll soon hear more about this ;-) Maurizio On 16/12/14 02:41, Tomas Mikula wrote: > On Sep 30, 2014, at 8:10 AM, Simon Ochsenreither ochsenreither.de> wrote: > >> There was a short mention of "conditional methods", e.g. enabling >> methods only for a subset of some generic type. > I don't know where conditional methods were mentioned and what their > current state is (any links?), but here is an idea how to get > conditional methods "for free" on top of two other (missing) features, > which would both be useful independently in their own right. > > The first feature is lower bounds on type parameters, i.e. , as in > > class Optional { > public Optional or(Optional other); > } > > The other one is to allow multiple type paramater bounds, even if one > of the bounds is itself a type variable. That is, allow bounds like extends T & Foo> or . > > I have no idea how technically feasible these features are, but I have > encountered use cases for both of them. > > Once we have lower bounds and multiple bounds, we can express > conditional methods like this: > > class Optional { > default int getAsInt() { > I value = get(); > return value.intValue(); > } > } > > Valid substitute for I exists only when T extends Integer, thus the > getAsInt() method can effectively be invoked only on > Optional. > > Regards, > Tomas From tomas.mikula at gmail.com Tue Dec 16 14:09:44 2014 From: tomas.mikula at gmail.com (Tomas Mikula) Date: Tue, 16 Dec 2014 15:09:44 +0100 Subject: Conditional methods "for free" In-Reply-To: References: Message-ID: Thanks, Ali, I knew someone must have had the same idea before :). Tomas On Tue, Dec 16, 2014 at 9:28 AM, Ali Ebrahimi wrote: > see > http://mail.openjdk.java.net/pipermail/lambda-dev/2010-November/002646.html > for history. > > On Tue, Dec 16, 2014 at 6:11 AM, Tomas Mikula > wrote: >> >> On Sep 30, 2014, at 8:10 AM, Simon Ochsenreither > ochsenreither.de> wrote: >> >> > There was a short mention of "conditional methods", e.g. enabling >> > methods only for a subset of some generic type. >> >> I don't know where conditional methods were mentioned and what their >> current state is (any links?), but here is an idea how to get >> conditional methods "for free" on top of two other (missing) features, >> which would both be useful independently in their own right. >> >> The first feature is lower bounds on type parameters, i.e. , as >> in >> >> class Optional { >> public Optional or(Optional other); >> } >> >> The other one is to allow multiple type paramater bounds, even if one >> of the bounds is itself a type variable. That is, allow bounds like > extends T & Foo> or . >> >> I have no idea how technically feasible these features are, but I have >> encountered use cases for both of them. >> >> Once we have lower bounds and multiple bounds, we can express >> conditional methods like this: >> >> class Optional { >> default int getAsInt() { >> I value = get(); >> return value.intValue(); >> } >> } >> >> Valid substitute for I exists only when T extends Integer, thus the >> getAsInt() method can effectively be invoked only on >> Optional. >> >> Regards, >> Tomas From tomas.mikula at gmail.com Tue Dec 16 14:10:58 2014 From: tomas.mikula at gmail.com (Tomas Mikula) Date: Tue, 16 Dec 2014 15:10:58 +0100 Subject: Conditional methods "for free" In-Reply-To: <549015E7.3000203@oracle.com> References: <549015E7.3000203@oracle.com> Message-ID: Thank you for your explanation. Tomas On Tue, Dec 16, 2014 at 12:22 PM, Maurizio Cimadamore wrote: > This is indeed a clever way to restrict applicability of certain methods to > specific receivers. However, applicability is only half of the story here; > the other half is membership. In your proposed solution, 'or' will be a > member of Optional - regardless of the parameterization of the generic > class. It seems likely that the feature we are after (not saying we have yet > arrived to a full solution here) will also restrict membership - i.e. 'or' > will simply not exist on an Optional (and then applicability would > of course follow). When migrating legacy, erasure-based code, it is in fact > fairly common to end up with cases in which existing methods > (Collection.remove(Object) anyone?) no longer make sense in a fully any-fied > world - and it is likely we will need a way that to say that those method > are only members of certain receivers but not others. > > That said, stay tuned, as you'll soon hear more about this ;-) > > Maurizio > > > On 16/12/14 02:41, Tomas Mikula wrote: >> >> On Sep 30, 2014, at 8:10 AM, Simon Ochsenreither > ochsenreither.de> wrote: >> >>> There was a short mention of "conditional methods", e.g. enabling >>> methods only for a subset of some generic type. >> >> I don't know where conditional methods were mentioned and what their >> current state is (any links?), but here is an idea how to get >> conditional methods "for free" on top of two other (missing) features, >> which would both be useful independently in their own right. >> >> The first feature is lower bounds on type parameters, i.e. , as >> in >> >> class Optional { >> public Optional or(Optional other); >> } >> >> The other one is to allow multiple type paramater bounds, even if one >> of the bounds is itself a type variable. That is, allow bounds like > extends T & Foo> or . >> >> I have no idea how technically feasible these features are, but I have >> encountered use cases for both of them. >> >> Once we have lower bounds and multiple bounds, we can express >> conditional methods like this: >> >> class Optional { >> default int getAsInt() { >> I value = get(); >> return value.intValue(); >> } >> } >> >> Valid substitute for I exists only when T extends Integer, thus the >> getAsInt() method can effectively be invoked only on >> Optional. >> >> Regards, >> Tomas > > From brian.goetz at oracle.com Fri Dec 19 21:31:40 2014 From: brian.goetz at oracle.com (Brian Goetz) Date: Fri, 19 Dec 2014 16:31:40 -0500 Subject: Updated State of the Specialization Message-ID: <5494993C.8000509@oracle.com> I've updated the State of the Specialization here: http://cr.openjdk.java.net/~briangoetz/valhalla/specialization.html The old version is here: http://cr.openjdk.java.net/~briangoetz/valhalla/specialization-1.html From timo.kinnunen at gmail.com Fri Dec 19 22:45:33 2014 From: timo.kinnunen at gmail.com (=?utf-8?Q?Timo_Kinnunen?=) Date: Fri, 19 Dec 2014 22:45:33 +0000 Subject: =?utf-8?Q?Re:_Updated_State_of_the_Specialization?= In-Reply-To: <5494993C.8000509@oracle.com> References: <5494993C.8000509@oracle.com> Message-ID: <5494afc0.a266b40a.4df0.ffff9672@mx.google.com> Hi, I?m not sure Peeling is necessary. The reason is that the problem it?s trying to solve already exists in the current Java and it has workarounds too. Here?s a demonstration with three ListLike adaptations and the workarounds: interface SmallList { public void remove(short position); public void remove(T element); } interface MediumList { public void remove(int position); public void remove(T element); } interface BigList { public void remove(BigInteger position); public void remove(T element); } public class Workaround { @SuppressWarnings({ "rawtypes", "unchecked" }) static void method(SmallList smallList, MediumList mediumList, BigList bigList) { smallList.remove((short) 3); smallList.remove((Short) (short) 3); mediumList.remove(3); mediumList.remove((Integer) 3); ((BigList) bigList).remove(BigInteger.valueOf(3)); ((BigList) bigList).remove((Object) BigInteger.valueOf(3)); } } For the record, none of the workarounds feel ?correct? to me, although the int/Integer pair gets close. Rather than Peeling, what I think is needed is to streamline overload selection so that the specialized methods are selected whenever possible and the non-specialized methods can be manually selected with extra casts, like this: smallList.remove((short) 3); smallList.remove(3); mediumList.remove((int) 3); mediumList.remove(3); bigList.remove((BigInteger) BigInteger.valueOf(3)); bigList.remove(BigInteger.valueOf(3)); -- Have a nice day, Timo. Sent from Windows Mail From: Brian Goetz Sent: ?Friday?, ?December? ?19?, ?2014 ?22?:?31 To: valhalla-dev at openjdk.java.net I've updated the State of the Specialization here: http://cr.openjdk.java.net/~briangoetz/valhalla/specialization.html The old version is here: http://cr.openjdk.java.net/~briangoetz/valhalla/specialization-1.html From ali.ebrahimi1781 at gmail.com Fri Dec 19 23:53:39 2014 From: ali.ebrahimi1781 at gmail.com (Ali Ebrahimi) Date: Sat, 20 Dec 2014 03:23:39 +0330 Subject: Updated State of the Specialization In-Reply-To: <5494afc0.a266b40a.4df0.ffff9672@mx.google.com> References: <5494993C.8000509@oracle.com> <5494afc0.a266b40a.4df0.ffff9672@mx.google.com> Message-ID: As long as I know, we currently have List and We try to specialize (or any-fy) that. How your solution handle List case? On Sat, Dec 20, 2014 at 2:15 AM, Timo Kinnunen wrote: > > Hi, > > > I?m not sure Peeling is necessary. The reason is that the problem it?s > trying to solve already exists in the current Java and it has workarounds > too. Here?s a demonstration with three ListLike adaptations and the > workarounds: > > > interface SmallList { > > public void remove(short position); > > public void remove(T element); > > } > > interface MediumList { > > public void remove(int position); > > public void remove(T element); > > } > > interface BigList { > > public void remove(BigInteger position); > > public void remove(T element); > > } > > > public class Workaround { > > @SuppressWarnings({ "rawtypes", "unchecked" }) > > static void method(SmallList smallList, MediumList > mediumList, BigList bigList) { > > > smallList.remove((short) 3); > > smallList.remove((Short) (short) 3); > > > mediumList.remove(3); > > mediumList.remove((Integer) 3); > > > ((BigList) bigList).remove(BigInteger.valueOf(3)); > > ((BigList) bigList).remove((Object) BigInteger.valueOf(3)); > > } > > } > > > For the record, none of the workarounds feel ?correct? to me, although the > int/Integer pair gets close. > > > Rather than Peeling, what I think is needed is to streamline overload > selection so that the specialized methods are selected whenever possible > and the non-specialized methods can be manually selected with extra casts, > like this: > > > > smallList.remove((short) 3); > > smallList.remove(3); > > > > > mediumList.remove((int) 3); > > mediumList.remove(3); > > > > > bigList.remove((BigInteger) BigInteger.valueOf(3)); > > bigList.remove(BigInteger.valueOf(3)); > > > > > -- > Have a nice day, > Timo. > > Sent from Windows Mail > > > > > > From: Brian Goetz > Sent: ?Friday?, ?December? ?19?, ?2014 ?22?:?31 > To: valhalla-dev at openjdk.java.net > > > > > > I've updated the State of the Specialization here: > http://cr.openjdk.java.net/~briangoetz/valhalla/specialization.html > > The old version is here: > http://cr.openjdk.java.net/~briangoetz/valhalla/specialization-1.html > From nipa at codefx.org Sat Dec 20 00:00:43 2014 From: nipa at codefx.org (Nicolai Parlog) Date: Sat, 20 Dec 2014 01:00:43 +0100 Subject: Updated State of the Specialization In-Reply-To: <5494993C.8000509@oracle.com> References: <5494993C.8000509@oracle.com> Message-ID: <5494BC2B.5060109@codefx.org> -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Hi! I'm sure I'm being stupid here but I can't find a difference between the old and the updated version (and neither can a text comparison tool). What am I missing? so long ... Nicolai On 19.12.2014 22:31, Brian Goetz wrote: > I've updated the State of the Specialization here: > http://cr.openjdk.java.net/~briangoetz/valhalla/specialization.html > > The old version is here: > http://cr.openjdk.java.net/~briangoetz/valhalla/specialization-1.html > > - -- PGP Key: http://keys.gnupg.net/pks/lookup?op=vindex&search=0xCA3BAD2E9CCCD509 Web: http://codefx.org a blog about software development http://do-foss.de Free and Open Source Software for the City of Dortmund Twitter: https://twitter.com/nipafx -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.22 (MingW32) iQIcBAEBAgAGBQJUlLwoAAoJEMo7rS6czNUJZKkP/3UBx+jkmz3WvEROWrfOcBJ8 /1iEUtmO9rV9SygfnIJgrC80YNZ3lqyCwQzzrUWJ/+nQhjh45R7AXf78NXLY6i1b fP1TXxulLJpFRr9tp7havmv1e8VCrkxBKfFkDpSanFg0lff+W89yBH+URdXMEqQs rh+jWSQ3q6CipCn0KLckyZ5h6jXwJHtFa9/T2XfC/x9wm/QfijZiJIRvQ+FqfrBQ aDyn+820K8i9GS19vh8uaHnbS1b3fEne3bioO7tz1zwkOMuMkyauMBmH3buu0dQq 7dG7UtUxZ8MziHKjeSH749ORXnKkXkvc7jNxATG0qD7Ep0Bynx+C9guhkRlYPs7Z rI9NChn61bYcfEtJ0YFK3lCHED2LU18Nr6SkxisqFchVk1Diadh6NrbnhJTcGkq/ Hpo6i4tguP0xIoWbIKDl2HNj84FDNhrlvABrih8uy7NQv2nvT+aLv8tbrV1rnEjr puczCLD4154vX1juLUTBcxz08MB9g1YdM/sd/Zf5Te/OjXb+zkHIjxwxC2p/tzuq 30hAXBThzwa2hfeBtQSuHUgCtyFPiHbDcHy6hxWQBlYjGJ9l3aNzEi16tGS7+KOi PXsH+GmUMLhKQebd+Ql874DgoFV8pL/sOgkwfxXKnWZgqU0pnrkKrOYK0trnrCli UqNKZQo0H+0MKKqDeVoN =ZOHN -----END PGP SIGNATURE----- From simon at ochsenreither.de Sat Dec 20 01:44:15 2014 From: simon at ochsenreither.de (Simon Ochsenreither) Date: Sat, 20 Dec 2014 02:44:15 +0100 (CET) Subject: Updated State of the Specialization In-Reply-To: <5494993C.8000509@oracle.com> References: <5494993C.8000509@oracle.com> Message-ID: <564593832.47313.1419039855813.JavaMail.open-xchange@srv005.service.ps-server.net> Hi everyone, Hi Brian, thanks for keeping us updated. Now that some of the basic parts seem to get a bit more stable, I'd like to ask some questions and raise some issues I'm seeing: Regarding rules about null and any-T values?: --------------------------------------------- Am I correct to assume that casting a null to a type is supported inside specialized code and results in the zero value of that type (null for references, 0/0.0/... for primitive types and e. g. Point(0,0) for value type Point(Int, Int))? Otherwise, what's the recommended way to "summon" a zero value for an arbitrary type? Comment on statics?: -------------------- This is absolutely the right call. .NET's behavior in that regard is a disaster of unknown proportions. Boxing ? value boxes vs. wrapper classes: ----------------------------------------- The draft seems to be very silent on the expected semantics of how value types are handled outside specialized code and how wrapper classes are handled inside specialized code. I think this is an important point, because every kind of mistake will directly effect thousands of users. Avoiding quirks here seems to be absolutely crucial to me (for instance, floating point numbers are hard enough to deal with even without letting users figure out the subtle differences between primitives, primitives-as-value-types, primitives-as-value-boxed-value-types and classic wrapped primitives). Primitive equality on value types/inside specialized code: ---------------------------------------------------------- Is there any further progress or additional insight into how this issue will be adressed, especially when boxing is involved? Partially specialized type hierarchies: --------------------------------------- Although it isn't spelt out in the draft it seems that it is possible to go from specialized to erased, but not from erased to specialized: Super ---> Sub< T> // ok Super< T> ---> Sub // not ok If this is correct, what's the story for types which are currently erased in byte code, because they can't be expressed with Java Generics (HKTs come to mind)? With that approach, all of that code would be permanently be stuck in no-specialization land (in the sense that even if the HKT couldn't be expressed with any-T, individual instantiations could ... but not under the scheme proposed in this draft). Manual control over specialization ---------------------------------- Maybe this chapter has some merit, but I feel that the reasons put forward are not very convincing: "Implementation by parts" argues a point which I'd consider a neat hack for a single use-case. In a language/world were Option was a value type, why would we even bother to pass Option(null)/Option(value) instead of null/value (in those simple cases)? "Overriding specific instantiations of specialized classes" might have some merit, but the example of ArrayList seems to be an incredibly poor choice to drive home the argument: [...] the implementation should pack the elements so that every bool only uses one bit of memory. This is widely considered a mistake. ?? Wikipedia on C++' vector Especially in everything-is-mutable-Java, having to lock 7 other values to update a single value doesn't seem to be a design decision fit for a general purpose class. (So we need some kind of BitSet, and then we can just implement it any way we want without needing this language feature.) "Specializing the specializations" I'm not sure this belongs here. Whether you want to add typeclasses to the language should be orthogonal to the topic of "manual control over specialization". "Overriding specific instantiations of generic methods" Valid point. The "Peeling" Technique?: ------------------------- To be honest, this feels like the draft is trying to fix one case of poor library design by adding a hugely complex language feature. Especially from a user perspective, this is probably as complicated as the rest of specialized generics plus value types combined. Having just read it again ... really, this is so absurdly complex for basically trying to work around two poor API decisions. That's a huge chunk from the complexity budget which I'd either spend on something more worthwhile?or not spend at all. Yes, one might argue that there could be other libraries out there which might have comparable issues, but you have to consider that most libraries out there don't follow the standard library's compatibility policy. Compatibility is regularly broken in major releases and it is usually not a big issue. If Oracle announces that in a very rare case things need to be adapted slightly (just as with every release Sun/Oracle ever announced) people will deal with it (just like with sun.misc.Unsafe going away). So it basically comes down to two method calls, Map#get and List#remove. Regarding Map#get: I'm not seeing an issue here. Returning the zero value for value types might be not very useful, but that's what happened for reference types for the last 15 years. I'd argue it's just not a problem which this draft should address. It's an issue of poor API design. An alternative method has already been introduced. If it's still such a pressing issue, introduce another method which returns Option instead of V|null. I'm not really seeing the issue this draft is supposed to solve here. Regarding List#remove: I think alternatives should be considered here. Wouldn't it be possible to allow the instantiation of List, but disallow the usage of List#remove by saying that the call is ambiguous? (Which it technically is!) In my opinion, something of this complexity shouldn't be put into a language, just because of an issue which occurs with _one_ method of _one_ interface given _one_ specific instantiation. It would be possible to introduce an annotation which is used for the error message if ambiguation fails, to steer people to the replacement methods mentioned in the draft. Scala is doing exactly this in implicit resolution, and it works well. interface List { @AmbiguityErrorMessage("Use `removeByIndex` instead.") E remove (int index) E removeByIndex(int index) @AmbiguityErrorMessage("Use `removeByValue` instead.") boolean remove (T element) boolean removeByValue(T element) } Summary: The draft looks good overall, but I think the reasons mentioned for adopting the "peeling technique" are extremely weak, while putting substantial language complexity in front of users. Thanks and bye, Simon ? http://cr.openjdk.java.net/~briangoetz/valhalla/specialization.html#language-restrictions ? http://cr.openjdk.java.net/~briangoetz/valhalla/specialization.html#statics ? http://cr.openjdk.java.net/~briangoetz/valhalla/specialization.html#manual-control-over-specialization ? http://cr.openjdk.java.net/~briangoetz/valhalla/specialization.html#the-peeling-technique From brian.goetz at oracle.com Sat Dec 20 02:43:08 2014 From: brian.goetz at oracle.com (Brian Goetz) Date: Fri, 19 Dec 2014 21:43:08 -0500 Subject: Updated State of the Specialization In-Reply-To: <564593832.47313.1419039855813.JavaMail.open-xchange@srv005.service.ps-server.net> References: <5494993C.8000509@oracle.com> <564593832.47313.1419039855813.JavaMail.open-xchange@srv005.service.ps-server.net> Message-ID: <5494E23C.3070009@oracle.com> > Regarding rules about null and any-T values?: > --------------------------------------------- > > Am I correct to assume that casting a null to a type is supported inside > specialized code and results in the zero value of that type (null for > references, 0/0.0/... for primitive types and e. g. Point(0,0) for value > type > Point(Int, Int))? We considered that approach, but it seemed a pretty bad idea. Null means "no object is there". But zero is a very useful and common integer; using zero to also mean "no number" seems infeasible. Returning zero from Map.get() in an int-valued Map when the element is not mapped seems even more error-prone than returning null in a ref-valued map. So we think null should retain its current meaning, and not define conversion from null to value types. > Otherwise, what's the recommended way to "summon" a zero value for an > arbitrary > type? Yes, there needs to be some way to do this; this is largely a syntax issue. Suffice it to say there will be some way to do this. > Boxing ? value boxes vs. wrapper classes: > ----------------------------------------- > > The draft seems to be very silent on the expected semantics of how value > types > are handled outside specialized code and how wrapper classes are handled > inside > specialized code. > > I think this is an important point, because every kind of mistake will > directly > effect thousands of users. Avoiding quirks here seems to be absolutely > crucial > to me (for instance, floating point numbers are hard enough to deal with > even > without letting users figure out the subtle differences between primitives, > primitives-as-value-types, primitives-as-value-boxed-value-types and > classic > wrapped primitives). This is indeed an important area to specify more carefully. It's on the list, but for now we've been mostly focusing on the mechanics of specialization. (Not because this is the end goal, but because without a working prototype, we can't do realistic experiments about the effect of these features on actual libraries, which is the real test.) > Primitive equality on value types/inside specialized code: > ---------------------------------------------------------- > > Is there any further progress or additional insight into how this > issue will be adressed, especially when boxing is involved? Not yet, that's also on the list. > Partially specialized type hierarchies: > --------------------------------------- > > Although it isn't spelt out in the draft it seems that it is possible to > go from > specialized to erased, but not from erased to specialized: > > Super ---> Sub< T> // ok > Super< T> ---> Sub // not ok Correct. Hierarchies need to be any-fied from the top down. > If this is correct, what's the story for types which are currently > erased in > byte code, because they can't be expressed with Java Generics (HKTs come to > mind)? > > With that approach, all of that code would be permanently be stuck in > no-specialization land (in the sense that even if the HKT couldn't be > expressed > with any-T, individual instantiations could ... but not under the scheme > proposed in this draft). Today, classes have two choices: - Non-generic - Erased generics We'll add a third choice: - Any-fied generics but we're not taking away the first two choices or changing anything about them. So at the very least, you have all the tools you currently have. If you want to suggest some use cases that you are hoping we can support, please do; we can't make any promises, but we're happy to have the input. > Manual control over specialization > ---------------------------------- > > Maybe this chapter has some merit, but I feel that the reasons put > forward are > not very convincing: > > "Implementation by parts" argues a point which I'd consider a neat hack > for a > single use-case. In a language/world were Option was a value type, why > would we > even bother to pass Option(null)/Option(value) instead of null/value (in > those > simple cases)? It's more than a single use case. When you look at the code for Collections, its rife with examples where implementation by parts is likely to be your only compatible choice. Further, this is something C# programmers complain about; you can't write a different implementation for value instantiations as for reference, and this is limiting. Reference implementations have tools (nulls, synchronization on object parameters) that value implementations don't have, and value implementations have tools (known non-polymorphism) that reference implementations don't have. > "Overriding specific instantiations of specialized classes" might have some > merit, but the example of ArrayList seems to be an incredibly poor > choice to drive home the argument: > > [...] the implementation should pack the elements so that every bool > only uses > one bit of memory. This is widely considered a mistake. > ?? Wikipedia on C++' vector Here's another example, then: the problem of "Maps from int to int" is a well-studied special case, with many clever implementation tricks that are not available to more general-purpose maps. But, your point is taken: "be careful of extrapolating from a small number of use cases." > The "Peeling" Technique?: > ------------------------- > > To be honest, this feels like the draft is trying to fix one case of > poor library > design by adding a hugely complex language feature. This is a fair concern; we've asked ourselves this multiple times. (The problems we face with any-fying collections are consequences of the corners that had to be cut in order to generify collections in the first place -- should we really be beholden to decisions that were made in 1997 after several major language evolutions?) And the prospect of adding a language feature that we hope no one has to use is not something to be taken lightly. But, we're also convinced that if our libraries have this problem, other libraries will too (and it's way more than one or two methods -- just try any-fying java.util.concurrent!) So I don't think it's "one case of poor library design". We'll know more once we have a more complete implementation and can do some corpus analysis on existing generic code. > Especially from a user perspective, this is probably as complicated as > the rest > of specialized generics plus value types combined. Yes, and herein is one of the most serious challenges of evolving a broad-spectrum language -- you can intend for a feature to be used only in certain situations or by certain users, but it is nearly impossible to make that guidance stick. > Having just read it again ... really, this is so absurdly complex for > basically > trying to work around two poor API decisions. That's a huge chunk from the > complexity budget which I'd either spend on something more worthwhile?or > not > spend at all. I wish it was just two. Perhaps a bet! I give you $1000 now, and you pay me $500 for every library out there that can't anyfy cleanly. I think you will fund my retirement... :) But, as I said, your point is by no means lost on us; we've asked ourselves this too, and will continue to do so. Right now, we're in the "can we make it work at all" phase; if we can make it work at all, we can then put effort towards simplifying. From peter.levart at gmail.com Sat Dec 20 11:34:54 2014 From: peter.levart at gmail.com (Peter Levart) Date: Sat, 20 Dec 2014 12:34:54 +0100 Subject: Statics issues Message-ID: <54955EDE.7060103@gmail.com> Hi, I joined the list yesterday and read the thread about static fields and initialization. I have a feeling the one-static-variable-per-source-definition is the desired direction. Especially when the number of specialized classes is an implementation detail. With one variable per class you would get separate variables per each primitive specialization combination, but reference type variables do not get specialized classes, which would be confusing. If static variables are a special case then this should be consistently applied to other areas: public class ValhallaTest { static int counter; static synchronized void count(T arg) { if (!Thread.holdsLock(ValhallaTest.class)) { throw new IllegalStateException("Not synchronized on ValhallaTest.class"); } counter++; System.out.println("Counting " + counter); } public static void main(String[] args) { count("A"); count(BigDecimal.ONE); count(1); System.out.println(counter); } } This prints: Counting 1 Counting 2 Specializing method ValhallaTest$count${0=I}.count(Ljava/lang/Object;)V with class=[] and method=[I] Exception in thread "main" java.lang.IllegalStateException: Not synchronized on ValhallaTest.class at ValhallaTest$count${0=I}/1096979270.count(ValhallaTest.java:12) at ValhallaTest.main(ValhallaTest.java:21) The specializer should also rewrite specialized synchronized static methods so they synchronize on the "host" class object. More "hiding" of specialized classes might be necessary. What would happen with the following code: void m(T arg) { synchronized(getClass()) { } } This could be "fixed" by not allowing things like Foo.class and making Object.getClass() always return the "host" class regardless of implementation class. But that means something like: this.getClass().cast(this) ...could throw ClassCastException then... This could be "fixed" by getClass() returning a special interface class object that is implemented by "host" class AND all specialized classes. Reflection issues left behind for now. I have doubts about "fixing" Object.getClass(), but for static synchronized methods I think they should be fixed. Regards, Peter From ali.ebrahimi1781 at gmail.com Sat Dec 20 12:10:58 2014 From: ali.ebrahimi1781 at gmail.com (Ali Ebrahimi) Date: Sat, 20 Dec 2014 15:40:58 +0330 Subject: Statics issues In-Reply-To: <54955EDE.7060103@gmail.com> References: <54955EDE.7060103@gmail.com> Message-ID: I think static synchronized methods issue can (should) be solved by generating specialized versions for generic methods in host class. We have ValhallaTest.count${0=I}(Ljava/lang/Object;)V What do you think? On Sat, Dec 20, 2014 at 3:04 PM, Peter Levart wrote: > Hi, > > I joined the list yesterday and read the thread about static fields and > initialization. I have a feeling the one-static-variable-per-source-definition > is the desired direction. Especially when the number of specialized classes > is an implementation detail. With one variable per class you would get > separate variables per each primitive specialization combination, but > reference type variables do not get specialized classes, which would be > confusing. > > If static variables are a special case then this should be consistently > applied to other areas: > > public class ValhallaTest { > > static int counter; > > static synchronized void count(T arg) { > if (!Thread.holdsLock(ValhallaTest.class)) { > throw new IllegalStateException("Not synchronized on > ValhallaTest.class"); > } > counter++; > System.out.println("Counting " + counter); > } > > public static void main(String[] args) { > count("A"); > count(BigDecimal.ONE); > count(1); > > System.out.println(counter); > } > } > > > This prints: > > Counting 1 > Counting 2 > Specializing method ValhallaTest$count${0=I}.count(Ljava/lang/Object;)V > with class=[] and method=[I] > Exception in thread "main" java.lang.IllegalStateException: Not > synchronized on ValhallaTest.class > at ValhallaTest$count${0=I}/1096979270.count(ValhallaTest.java:12) > at ValhallaTest.main(ValhallaTest.java:21) > > > The specializer should also rewrite specialized synchronized static > methods so they synchronize on the "host" class object. > > More "hiding" of specialized classes might be necessary. What would happen > with the following code: > > void m(T arg) { > synchronized(getClass()) { > } > } > > This could be "fixed" by not allowing things like Foo.class and > making Object.getClass() always return the "host" class regardless of > implementation class. But that means something like: > > this.getClass().cast(this) > > ...could throw ClassCastException then... > > This could be "fixed" by getClass() returning a special interface class > object that is implemented by "host" class AND all specialized classes. > > Reflection issues left behind for now. > > I have doubts about "fixing" Object.getClass(), but for static > synchronized methods I think they should be fixed. > > Regards, Peter > > From timo.kinnunen at gmail.com Sat Dec 20 12:24:02 2014 From: timo.kinnunen at gmail.com (=?utf-8?Q?Timo_Kinnunen?=) Date: Sat, 20 Dec 2014 12:24:02 +0000 Subject: =?utf-8?Q?Re:_Updated_State_of_the_Specialization?= In-Reply-To: References: <5494993C.8000509@oracle.com> <5494afc0.a266b40a.4df0.ffff9672@mx.google.com>, Message-ID: <54956e40.d38ec20a.7ade.2ef1@mx.google.com> Here an anyfied List version and a demo: interface List { public void remove(int position); public void remove(T element); static void test(List list) { // calls remove(int position); list.remove((int) 3); // calls remove(T element); list.remove(3); } } The choice of which method to prefer with the plain, cast-less version is somewhat arbitrary. My rationale for preferring it like this rather than the other way around is that the specialized type is more interesting. Thus the compiler should make calling methods taking one as easy as possible. -- Have a nice day, Timo. Sent from Windows Mail From: Ali Ebrahimi Sent: ?Saturday?, ?December? ?20?, ?2014 ?0?:?53 To: Timo Kinnunen Cc: Brian Goetz, valhalla-dev at openjdk.java.net As long as I know, we currently have List and We try to specialize (or any-fy) that. How your solution handle List case? On Sat, Dec 20, 2014 at 2:15 AM, Timo Kinnunen wrote: Hi, I?m not sure Peeling is necessary. The reason is that the problem it?s trying to solve already exists in the current Java and it has workarounds too. Here?s a demonstration with three ListLike adaptations and the workarounds: interface SmallList { public void remove(short position); public void remove(T element); } interface MediumList { public void remove(int position); public void remove(T element); } interface BigList { public void remove(BigInteger position); public void remove(T element); } public class Workaround { @SuppressWarnings({ "rawtypes", "unchecked" }) static void method(SmallList smallList, MediumList mediumList, BigList bigList) { smallList.remove((short) 3); smallList.remove((Short) (short) 3); mediumList.remove(3); mediumList.remove((Integer) 3); ((BigList) bigList).remove(BigInteger.valueOf(3)); ((BigList) bigList).remove((Object) BigInteger.valueOf(3)); } } For the record, none of the workarounds feel ?correct? to me, although the int/Integer pair gets close. Rather than Peeling, what I think is needed is to streamline overload selection so that the specialized methods are selected whenever possible and the non-specialized methods can be manually selected with extra casts, like this: smallList.remove((short) 3); smallList.remove(3); mediumList.remove((int) 3); mediumList.remove(3); bigList.remove((BigInteger) BigInteger.valueOf(3)); bigList.remove(BigInteger.valueOf(3)); -- Have a nice day, Timo. Sent from Windows Mail From: Brian Goetz Sent: ?Friday?, ?December? ?19?, ?2014 ?22?:?31 To: valhalla-dev at openjdk.java.net I've updated the State of the Specialization here: http://cr.openjdk.java.net/~briangoetz/valhalla/specialization.html The old version is here: http://cr.openjdk.java.net/~briangoetz/valhalla/specialization-1.html From timo.kinnunen at gmail.com Sat Dec 20 13:08:24 2014 From: timo.kinnunen at gmail.com (=?utf-8?Q?Timo_Kinnunen?=) Date: Sat, 20 Dec 2014 13:08:24 +0000 Subject: =?utf-8?Q?Re:_Updated_State_of_the_Specialization?= In-Reply-To: <5494E23C.3070009@oracle.com> References: <5494993C.8000509@oracle.com> <564593832.47313.1419039855813.JavaMail.open-xchange@srv005.service.ps-server.net>, <5494E23C.3070009@oracle.com> Message-ID: <54959f58.4253b40a.4a4b.56fc@mx.google.com> Regarding ?But, we're also convinced that if our libraries have this problem, other libraries will too (and it's way more than one or two methods -- just try any-fying java.util.concurrent!) ? I think the choice of straw syntax might be leading you astray. I view the problem of any-fying a library as essentially the same as annotating a library for Nullness. And there?s a lot existing work for that task already. To demonstrate, a fully, explicitly (and a bit redundantly) annotated Map could look like this: interface Map<@NonNull K, @NonNull V> { @NonNull V getOrDefault(@NonNull K key, @NonNull V value); @Nullable V get(@NonNull K key); } If we specialize that Map for , we?ll have these methods: @NonNull Integer getOrDefault(@NonNull Integer key, @NonNull Integer value); @Nullable Integer get(@NonNull Integer key); The @NonNull Integer is not a real type, but if it were made to be a real type it might as well be defined as @NonNull Integer == int (1). The methods could be written thusly: int getOrDefault(int key, int value); @Nullable Integer get(int key); There?s still that one @Nullable Integer there, but let?s pretend == <@NonNull T> and rewrite the null-annotated Map that we started with: interface Map { V getOrDefault(K key, V value); @Nullable V get(K key); } This looks quite like the straw syntax now. That @Nullable V which turns into @Nullable int which turns into Integer is telling you that the tool that you are missing and that?s blocking you from any-fying libraries is the lack of boxing for value types (2). Once that?s sorted out the rest should become much easier. 1) Defining @NonNull Integer == int has a lot of neat effects. For example, new Integer(42) is naturally a @NonNull Integer, as is also Integer.valueOf(42). 2) There?s also the comedy option of using an Optional with an isPresent field, which is reinventing both boxing and null-as-no-value. -- Have a nice day, Timo. Sent from Windows Mail From: Brian Goetz Sent: ?Saturday?, ?December? ?20?, ?2014 ?3?:?43 To: Simon Ochsenreither, valhalla-dev at openjdk.java.net > Regarding rules about null and any-T values?: > --------------------------------------------- > > Am I correct to assume that casting a null to a type is supported inside > specialized code and results in the zero value of that type (null for > references, 0/0.0/... for primitive types and e. g. Point(0,0) for value > type > Point(Int, Int))? We considered that approach, but it seemed a pretty bad idea. Null means "no object is there". But zero is a very useful and common integer; using zero to also mean "no number" seems infeasible. Returning zero from Map.get() in an int-valued Map when the element is not mapped seems even more error-prone than returning null in a ref-valued map. So we think null should retain its current meaning, and not define conversion from null to value types. > Otherwise, what's the recommended way to "summon" a zero value for an > arbitrary > type? Yes, there needs to be some way to do this; this is largely a syntax issue. Suffice it to say there will be some way to do this. > Boxing ? value boxes vs. wrapper classes: > ----------------------------------------- > > The draft seems to be very silent on the expected semantics of how value > types > are handled outside specialized code and how wrapper classes are handled > inside > specialized code. > > I think this is an important point, because every kind of mistake will > directly > effect thousands of users. Avoiding quirks here seems to be absolutely > crucial > to me (for instance, floating point numbers are hard enough to deal with > even > without letting users figure out the subtle differences between primitives, > primitives-as-value-types, primitives-as-value-boxed-value-types and > classic > wrapped primitives). This is indeed an important area to specify more carefully. It's on the list, but for now we've been mostly focusing on the mechanics of specialization. (Not because this is the end goal, but because without a working prototype, we can't do realistic experiments about the effect of these features on actual libraries, which is the real test.) > Primitive equality on value types/inside specialized code: > ---------------------------------------------------------- > > Is there any further progress or additional insight into how this > issue will be adressed, especially when boxing is involved? Not yet, that's also on the list. > Partially specialized type hierarchies: > --------------------------------------- > > Although it isn't spelt out in the draft it seems that it is possible to > go from > specialized to erased, but not from erased to specialized: > > Super ---> Sub< T> // ok > Super< T> ---> Sub // not ok Correct. Hierarchies need to be any-fied from the top down. > If this is correct, what's the story for types which are currently > erased in > byte code, because they can't be expressed with Java Generics (HKTs come to > mind)? > > With that approach, all of that code would be permanently be stuck in > no-specialization land (in the sense that even if the HKT couldn't be > expressed > with any-T, individual instantiations could ... but not under the scheme > proposed in this draft). Today, classes have two choices: - Non-generic - Erased generics We'll add a third choice: - Any-fied generics but we're not taking away the first two choices or changing anything about them. So at the very least, you have all the tools you currently have. If you want to suggest some use cases that you are hoping we can support, please do; we can't make any promises, but we're happy to have the input. > Manual control over specialization > ---------------------------------- > > Maybe this chapter has some merit, but I feel that the reasons put > forward are > not very convincing: > > "Implementation by parts" argues a point which I'd consider a neat hack > for a > single use-case. In a language/world were Option was a value type, why > would we > even bother to pass Option(null)/Option(value) instead of null/value (in > those > simple cases)? It's more than a single use case. When you look at the code for Collections, its rife with examples where implementation by parts is likely to be your only compatible choice. Further, this is something C# programmers complain about; you can't write a different implementation for value instantiations as for reference, and this is limiting. Reference implementations have tools (nulls, synchronization on object parameters) that value implementations don't have, and value implementations have tools (known non-polymorphism) that reference implementations don't have. > "Overriding specific instantiations of specialized classes" might have some > merit, but the example of ArrayList seems to be an incredibly poor > choice to drive home the argument: > > [...] the implementation should pack the elements so that every bool > only uses > one bit of memory. This is widely considered a mistake. > ?? Wikipedia on C++' vector Here's another example, then: the problem of "Maps from int to int" is a well-studied special case, with many clever implementation tricks that are not available to more general-purpose maps. But, your point is taken: "be careful of extrapolating from a small number of use cases." > The "Peeling" Technique?: > ------------------------- > > To be honest, this feels like the draft is trying to fix one case of > poor library > design by adding a hugely complex language feature. This is a fair concern; we've asked ourselves this multiple times. (The problems we face with any-fying collections are consequences of the corners that had to be cut in order to generify collections in the first place -- should we really be beholden to decisions that were made in 1997 after several major language evolutions?) And the prospect of adding a language feature that we hope no one has to use is not something to be taken lightly. But, we're also convinced that if our libraries have this problem, other libraries will too (and it's way more than one or two methods -- just try any-fying java.util.concurrent!) So I don't think it's "one case of poor library design". We'll know more once we have a more complete implementation and can do some corpus analysis on existing generic code. > Especially from a user perspective, this is probably as complicated as > the rest > of specialized generics plus value types combined. Yes, and herein is one of the most serious challenges of evolving a broad-spectrum language -- you can intend for a feature to be used only in certain situations or by certain users, but it is nearly impossible to make that guidance stick. > Having just read it again ... really, this is so absurdly complex for > basically > trying to work around two poor API decisions. That's a huge chunk from the > complexity budget which I'd either spend on something more worthwhile?or > not > spend at all. I wish it was just two. Perhaps a bet! I give you $1000 now, and you pay me $500 for every library out there that can't anyfy cleanly. I think you will fund my retirement... :) But, as I said, your point is by no means lost on us; we've asked ourselves this too, and will continue to do so. Right now, we're in the "can we make it work at all" phase; if we can make it work at all, we can then put effort towards simplifying. From ali.ebrahimi1781 at gmail.com Sat Dec 20 18:04:54 2014 From: ali.ebrahimi1781 at gmail.com (Ali Ebrahimi) Date: Sat, 20 Dec 2014 21:34:54 +0330 Subject: Updated State of the Specialization In-Reply-To: <54956e40.d38ec20a.7ade.2ef1@mx.google.com> References: <5494993C.8000509@oracle.com> <5494afc0.a266b40a.4df0.ffff9672@mx.google.com> <54956e40.d38ec20a.7ade.2ef1@mx.google.com> Message-ID: What is instantiated type var for T in List? Integer or int On Sat, Dec 20, 2014 at 3:54 PM, Timo Kinnunen wrote: > Here an anyfied List version and a demo: > > interface List { > public void remove(int position); > public void remove(T element); > > static void test(List list) { > > // calls remove(int position); > list.remove((int) 3); > > // calls remove(T element); > list.remove(3); > } > } > > The choice of which method to prefer with the plain, cast-less version is > somewhat arbitrary. My rationale for preferring it like this rather than > the other way around is that the specialized type is more interesting. Thus > the compiler should make calling methods taking one as easy as possible. > > -- > Have a nice day, > Timo. > > Sent from Windows Mail > > *From:* Ali Ebrahimi > *Sent:* ?Saturday?, ?December? ?20?, ?2014 ?0?:?53 > *To:* Timo Kinnunen > *Cc:* Brian Goetz , valhalla-dev at openjdk.java.net > > As long as I know, we currently have List and We try to specialize (or > any-fy) that. > How your solution handle List case? > > > On Sat, Dec 20, 2014 at 2:15 AM, Timo Kinnunen > wrote: >> >> Hi, >> >> >> I?m not sure Peeling is necessary. The reason is that the problem it?s >> trying to solve already exists in the current Java and it has workarounds >> too. Here?s a demonstration with three ListLike adaptations and the >> workarounds: >> >> >> interface SmallList { >> >> public void remove(short position); >> >> public void remove(T element); >> >> } >> >> interface MediumList { >> >> public void remove(int position); >> >> public void remove(T element); >> >> } >> >> interface BigList { >> >> public void remove(BigInteger position); >> >> public void remove(T element); >> >> } >> >> >> public class Workaround { >> >> @SuppressWarnings({ "rawtypes", "unchecked" }) >> >> static void method(SmallList smallList, MediumList >> mediumList, BigList bigList) { >> >> >> smallList.remove((short) 3); >> >> smallList.remove((Short) (short) 3); >> >> >> mediumList.remove(3); >> >> mediumList.remove((Integer) 3); >> >> >> ((BigList) bigList).remove(BigInteger.valueOf(3)); >> >> ((BigList) bigList).remove((Object) BigInteger.valueOf(3)); >> >> } >> >> } >> >> >> For the record, none of the workarounds feel ?correct? to me, although >> the int/Integer pair gets close. >> >> >> Rather than Peeling, what I think is needed is to streamline overload >> selection so that the specialized methods are selected whenever possible >> and the non-specialized methods can be manually selected with extra casts, >> like this: >> >> >> >> smallList.remove((short) 3); >> >> smallList.remove(3); >> >> >> >> >> mediumList.remove((int) 3); >> >> mediumList.remove(3); >> >> >> >> >> bigList.remove((BigInteger) BigInteger.valueOf(3)); >> >> bigList.remove(BigInteger.valueOf(3)); >> >> >> >> >> -- >> Have a nice day, >> Timo. >> >> Sent from Windows Mail >> >> >> >> >> >> From: Brian Goetz >> Sent: ?Friday?, ?December? ?19?, ?2014 ?22?:?31 >> To: valhalla-dev at openjdk.java.net >> >> >> >> >> >> I've updated the State of the Specialization here: >> http://cr.openjdk.java.net/~briangoetz/valhalla/specialization.html >> >> The old version is here: >> http://cr.openjdk.java.net/~briangoetz/valhalla/specialization-1.html >> > From timo.kinnunen at gmail.com Sat Dec 20 18:11:59 2014 From: timo.kinnunen at gmail.com (=?utf-8?Q?Timo_Kinnunen?=) Date: Sat, 20 Dec 2014 18:11:59 +0000 Subject: =?utf-8?Q?Re:_Updated_State_of_the_Specialization?= In-Reply-To: References: <5494993C.8000509@oracle.com> <5494afc0.a266b40a.4df0.ffff9672@mx.google.com> <54956e40.d38ec20a.7ade.2ef1@mx.google.com>, Message-ID: <5495be36.6153c20a.04b7.ffff864b@mx.google.com> It is int, so you end up with two methods in the API which both take the same type and a need to distinguish between them somehow. This is analogous to the BigList example from the previous email. There the problem was about choosing between one method taking a normal BigInteger and another taking an ?erasable? BigInteger. Here the problem is about choosing between one method taking a plain int and another method taking a ?valuable? int. -- Have a nice day, Timo. Sent from Windows Mail From: Ali Ebrahimi Sent: ?Saturday?, ?December? ?20?, ?2014 ?19?:?04 To: Timo Kinnunen Cc: valhalla-dev at openjdk.java.net What is instantiated type var for T in List? Integer or int On Sat, Dec 20, 2014 at 3:54 PM, Timo Kinnunen wrote: Here an anyfied List version and a demo: interface List { public void remove(int position); public void remove(T element); static void test(List list) { // calls remove(int position); list.remove((int) 3); // calls remove(T element); list.remove(3); } } The choice of which method to prefer with the plain, cast-less version is somewhat arbitrary. My rationale for preferring it like this rather than the other way around is that the specialized type is more interesting. Thus the compiler should make calling methods taking one as easy as possible. -- Have a nice day, Timo. Sent from Windows Mail From: Ali Ebrahimi Sent: ?Saturday?, ?December? ?20?, ?2014 ?0?:?53 To: Timo Kinnunen Cc: Brian Goetz, valhalla-dev at openjdk.java.net As long as I know, we currently have List and We try to specialize (or any-fy) that. How your solution handle List case? On Sat, Dec 20, 2014 at 2:15 AM, Timo Kinnunen wrote: Hi, I?m not sure Peeling is necessary. The reason is that the problem it?s trying to solve already exists in the current Java and it has workarounds too. Here?s a demonstration with three ListLike adaptations and the workarounds: interface SmallList { public void remove(short position); public void remove(T element); } interface MediumList { public void remove(int position); public void remove(T element); } interface BigList { public void remove(BigInteger position); public void remove(T element); } public class Workaround { @SuppressWarnings({ "rawtypes", "unchecked" }) static void method(SmallList smallList, MediumList mediumList, BigList bigList) { smallList.remove((short) 3); smallList.remove((Short) (short) 3); mediumList.remove(3); mediumList.remove((Integer) 3); ((BigList) bigList).remove(BigInteger.valueOf(3)); ((BigList) bigList).remove((Object) BigInteger.valueOf(3)); } } For the record, none of the workarounds feel ?correct? to me, although the int/Integer pair gets close. Rather than Peeling, what I think is needed is to streamline overload selection so that the specialized methods are selected whenever possible and the non-specialized methods can be manually selected with extra casts, like this: smallList.remove((short) 3); smallList.remove(3); mediumList.remove((int) 3); mediumList.remove(3); bigList.remove((BigInteger) BigInteger.valueOf(3)); bigList.remove(BigInteger.valueOf(3)); -- Have a nice day, Timo. Sent from Windows Mail From: Brian Goetz Sent: ?Friday?, ?December? ?19?, ?2014 ?22?:?31 To: valhalla-dev at openjdk.java.net I've updated the State of the Specialization here: http://cr.openjdk.java.net/~briangoetz/valhalla/specialization.html The old version is here: http://cr.openjdk.java.net/~briangoetz/valhalla/specialization-1.html From ali.ebrahimi1781 at gmail.com Sat Dec 20 18:36:37 2014 From: ali.ebrahimi1781 at gmail.com (Ali Ebrahimi) Date: Sat, 20 Dec 2014 22:06:37 +0330 Subject: Updated State of the Specialization In-Reply-To: <5495be36.6153c20a.04b7.ffff864b@mx.google.com> References: <5494993C.8000509@oracle.com> <5494afc0.a266b40a.4df0.ffff9672@mx.google.com> <54956e40.d38ec20a.7ade.2ef1@mx.google.com> <5495be36.6153c20a.04b7.ffff864b@mx.google.com> Message-ID: what is your translation scheme for specialization? is that Brian's Or ... I'm confused, from your response T instantiated as ?valuable? int not int? I'm correct? On Sat, Dec 20, 2014 at 9:41 PM, Timo Kinnunen wrote: > It is int, so you end up with two methods in the API which both take the > same type and a need to distinguish between them somehow. > > This is analogous to the BigList example from the previous > email. There the problem was about choosing between one method taking a > normal BigInteger and another taking an ?erasable? BigInteger. > > Here the problem is about choosing between one method taking a plain int > and another method taking a ?valuable? int. > > > > > -- > Have a nice day, > Timo. > > Sent from Windows Mail > > *From:* Ali Ebrahimi > *Sent:* ?Saturday?, ?December? ?20?, ?2014 ?19?:?04 > *To:* Timo Kinnunen > *Cc:* valhalla-dev at openjdk.java.net > > What is instantiated type var for T in List? Integer or int > > On Sat, Dec 20, 2014 at 3:54 PM, Timo Kinnunen > wrote: > >> Here an anyfied List version and a demo: >> >> interface List { >> public void remove(int position); >> public void remove(T element); >> >> static void test(List list) { >> >> // calls remove(int position); >> list.remove((int) 3); >> >> // calls remove(T element); >> list.remove(3); >> } >> } >> >> The choice of which method to prefer with the plain, cast-less version is >> somewhat arbitrary. My rationale for preferring it like this rather than >> the other way around is that the specialized type is more interesting. Thus >> the compiler should make calling methods taking one as easy as possible. >> >> -- >> Have a nice day, >> Timo. >> >> Sent from Windows Mail >> >> *From:* Ali Ebrahimi >> *Sent:* ?Saturday?, ?December? ?20?, ?2014 ?0?:?53 >> *To:* Timo Kinnunen >> *Cc:* Brian Goetz , valhalla-dev at openjdk.java.net >> >> As long as I know, we currently have List and We try to specialize (or >> any-fy) that. >> How your solution handle List case? >> >> >> On Sat, Dec 20, 2014 at 2:15 AM, Timo Kinnunen >> wrote: >>> >>> Hi, >>> >>> >>> I?m not sure Peeling is necessary. The reason is that the problem it?s >>> trying to solve already exists in the current Java and it has workarounds >>> too. Here?s a demonstration with three ListLike adaptations and the >>> workarounds: >>> >>> >>> interface SmallList { >>> >>> public void remove(short position); >>> >>> public void remove(T element); >>> >>> } >>> >>> interface MediumList { >>> >>> public void remove(int position); >>> >>> public void remove(T element); >>> >>> } >>> >>> interface BigList { >>> >>> public void remove(BigInteger position); >>> >>> public void remove(T element); >>> >>> } >>> >>> >>> public class Workaround { >>> >>> @SuppressWarnings({ "rawtypes", "unchecked" }) >>> >>> static void method(SmallList smallList, MediumList >>> mediumList, BigList bigList) { >>> >>> >>> smallList.remove((short) 3); >>> >>> smallList.remove((Short) (short) 3); >>> >>> >>> mediumList.remove(3); >>> >>> mediumList.remove((Integer) 3); >>> >>> >>> ((BigList) bigList).remove(BigInteger.valueOf(3)); >>> >>> ((BigList) bigList).remove((Object) BigInteger.valueOf(3)); >>> >>> } >>> >>> } >>> >>> >>> For the record, none of the workarounds feel ?correct? to me, although >>> the int/Integer pair gets close. >>> >>> >>> Rather than Peeling, what I think is needed is to streamline overload >>> selection so that the specialized methods are selected whenever possible >>> and the non-specialized methods can be manually selected with extra casts, >>> like this: >>> >>> >>> >>> smallList.remove((short) 3); >>> >>> smallList.remove(3); >>> >>> >>> >>> >>> mediumList.remove((int) 3); >>> >>> mediumList.remove(3); >>> >>> >>> >>> >>> bigList.remove((BigInteger) BigInteger.valueOf(3)); >>> >>> bigList.remove(BigInteger.valueOf(3)); >>> >>> >>> >>> >>> -- >>> Have a nice day, >>> Timo. >>> >>> Sent from Windows Mail >>> >>> >>> >>> >>> >>> From: Brian Goetz >>> Sent: ?Friday?, ?December? ?19?, ?2014 ?22?:?31 >>> To: valhalla-dev at openjdk.java.net >>> >>> >>> >>> >>> >>> I've updated the State of the Specialization here: >>> http://cr.openjdk.java.net/~briangoetz/valhalla/specialization.html >>> >>> The old version is here: >>> http://cr.openjdk.java.net/~briangoetz/valhalla/specialization-1.html >>> >> > From simon at ochsenreither.de Sat Dec 20 19:05:58 2014 From: simon at ochsenreither.de (Simon Ochsenreither) Date: Sat, 20 Dec 2014 20:05:58 +0100 Subject: Updated State of the Specialization In-Reply-To: <5494E23C.3070009@oracle.com> References: <5494993C.8000509@oracle.com> <564593832.47313.1419039855813.JavaMail.open-xchange@srv005.service.ps-server.net> <5494E23C.3070009@oracle.com> Message-ID: <5495C896.7070103@ochsenreither.de> > We considered that approach, but it seemed a pretty bad idea. Null > means "no object is there". But zero is a very useful and common > integer; using zero to also mean "no number" seems infeasible. > Returning zero from Map.get() in an int-valued Map when the element is > not mapped seems even more error-prone than returning null in a > ref-valued map. So we think null should retain its current meaning, > and not define conversion from null to value types. I'm not sure I understand the connection you are making to Map#get here... Yes, it's a poor API, but why is it the job of this draft to fix it? Imho, a real fix would be to provide an alternative method which works better, not to introduce a huge language feature to work around one method. I don't want to imagine how the JVM/Java will look like if you add language feature work-arounds for every case of poor API design. > Yes, there needs to be some way to do this; this is largely a syntax > issue. Suffice it to say there will be some way to do this. Regarding zero values of T, I'm not even sure something like (int) null works in Java, but Scala does it consistently with null.asInstanceOf[T]. (If or how the syntax will work in Java is not my main interest here. What matters is the bytecode. There were also a few ideas in the past to wrap this idiom in a "nicer" API like def default[T] = null.asInstanceOf[T] in Scala, but considering that a) the use of zero values is not that high b) null.asInstanceOf[T] works fine as an idiom, no further action was taken.) With the introduction of value types there needs to be a way to achieve this in bytecode, because an approach where you first check for every primitive type and return null otherwise just doesn't work with user-definable value types. Of course one could just do new Array[T](1)(0) but it's kind of ridiculous to create an one-element array just to pull out the uninitialized element. > Today, classes have two choices: > - Non-generic > - Erased generics > > We'll add a third choice: > - Any-fied generics > > but we're not taking away the first two choices or changing anything > about them. So at the very least, you have all the tools you > currently have. If you want to suggest some use cases that you are > hoping we can support, please do; we can't make any promises, but > we're happy to have the input. I think it would be kind of embarrassing to create ? in the same draft which tries to solve the issue that people have to decide between abstraction and performance (e. g. one generic method vs. one method for refs plus 8 methods for primitives) ? the same issue again, just in a different place (HKT abstraction vs. performance). It feels a bit like that with the current draft specialization will end up as another Java-only feature, like Java 8's defender methods or Java 8's function types. Imho, that would be unfortunate. > It's more than a single use case. When you look at the code for > Collections, its rife with examples where implementation by parts is > likely to be your only compatible choice. Further, this is something > C# programmers complain about; you can't write a different > implementation for value instantiations as for reference, and this is > limiting. Reference implementations have tools (nulls, synchronization > on object parameters) that value implementations don't have, and value > implementations have tools (known non-polymorphism) that reference > implementations don't have. I'd love to see an example. It hasn't been an issue in Scala so far. (When object-like tools are required in some places, the upper bounds reflect that, but that's about it.) > Here's another example, then: the problem of "Maps from int to int" is > a well-studied special case, with many clever implementation tricks > that are not available to more general-purpose maps. That's certainly a better example! I'm not sure whether creating the chance of having subtle behavioral differences between different collection instantiations is an acceptable price to pay for that, though. > But, we're also convinced that if our libraries have this problem, > other libraries will too (and it's way more than one or two methods -- > just try any-fying java.util.concurrent!) So I don't think it's "one > case of poor library design". We'll know more once we have a more > complete implementation and can do some corpus analysis on existing > generic code. The main issue for JDK libraries is that they can't be changed anymore, a problem which just doesn't exist for pretty much all other libraries out there. > I wish it was just two. Perhaps a bet! I give you $1000 now, and you > pay me $500 for every library out there that can't anyfy cleanly. I > think you will fund my retirement... :) For non-JDK libraries, moving to Java 10 is an explicit choice. Existing code will not break and if you think about the impact of having to slightly adapt a library for Java 10, especially compared to the upcoming _real_ breaking changes like modularization or sun.misc.Unsafe this is completely negligible from my perspective. Every library who wants to use Java 10 features needs to be adapted manually anyway; just slapping "any" on type parameters won't work, so making sure that clashing methods have non-clashing alternatives is probably not the biggest issue by far when migrating to Java 10. Which example would be unable to be handled with the approach I described? I think that approach combines non-intrusiveness on the library level and non-intrusiveness on the language level, clean & well-known semantics and an easy upgrade path (which could even be automated in some cases). From simon at ochsenreither.de Sat Dec 20 19:08:55 2014 From: simon at ochsenreither.de (Simon Ochsenreither) Date: Sat, 20 Dec 2014 20:08:55 +0100 Subject: Updated State of the Specialization In-Reply-To: <5495be36.6153c20a.04b7.ffff864b@mx.google.com> References: <5494993C.8000509@oracle.com> <5494afc0.a266b40a.4df0.ffff9672@mx.google.com> <54956e40.d38ec20a.7ade.2ef1@mx.google.com>, <5495be36.6153c20a.04b7.ffff864b@mx.google.com> Message-ID: <5495C947.4020405@ochsenreither.de> > Here the problem is about choosing between one method taking a plain int and another method taking a ?valuable? int. As mentioned, what's the issue with _not_ choosing one method when methods are ambiguous, just like in every other case when the compiler experiences an ambiguity issue? Just reject that line of code. Done. From timo.kinnunen at gmail.com Sat Dec 20 20:02:13 2014 From: timo.kinnunen at gmail.com (=?utf-8?Q?Timo_Kinnunen?=) Date: Sat, 20 Dec 2014 20:02:13 +0000 Subject: =?utf-8?Q?Re:_Updated_State_of_the_Specialization?= In-Reply-To: <5495C947.4020405@ochsenreither.de> References: <5494993C.8000509@oracle.com> <5494afc0.a266b40a.4df0.ffff9672@mx.google.com> <54956e40.d38ec20a.7ade.2ef1@mx.google.com>, <5495be36.6153c20a.04b7.ffff864b@mx.google.com>, <5495C947.4020405@ochsenreither.de> Message-ID: <5495da61.a716c20a.1016.ffffac50@mx.google.com> The issue is that it forces users to write really really ugly code as a workaround. In Java 8 the BigList specialization interface BigList { public void remove(BigInteger position); public void remove(T element); } BigList bigList; BigInteger value; needs to be called like this: // calls remove(BigInteger position) ((BigList) bigList).remove(value); // calls remove(T element) with T=BigInteger ((BigList) bigList).remove((Object) value); when it could be called like this: // calls remove(BigInteger position) bigList.remove((BigInteger) value); // calls remove(T element) with T=BigInteger bigList.remove(value); Perhaps in Java 10 it will end up being called like this: // calls remove(BigInteger position) bigList.remove((BigInteger) value); // calls remove(T element) with any T=BigInteger bigList.remove((any BigInteger) value); but I would prefer to reuse the existing cast-syntax instead. -- Have a nice day, Timo. Sent from Windows Mail From: Simon Ochsenreither Sent: ?Saturday?, ?December? ?20?, ?2014 ?20?:?08 To: valhalla-dev at openjdk.java.net > Here the problem is about choosing between one method taking a plain int and another method taking a ?valuable? int. As mentioned, what's the issue with _not_ choosing one method when methods are ambiguous, just like in every other case when the compiler experiences an ambiguity issue? Just reject that line of code. Done. From timo.kinnunen at gmail.com Sat Dec 20 20:22:04 2014 From: timo.kinnunen at gmail.com (=?utf-8?Q?Timo_Kinnunen?=) Date: Sat, 20 Dec 2014 20:22:04 +0000 Subject: =?utf-8?Q?Re:_Updated_State_of_the_Specialization?= In-Reply-To: References: <5494993C.8000509@oracle.com> <5494afc0.a266b40a.4df0.ffff9672@mx.google.com> <54956e40.d38ec20a.7ade.2ef1@mx.google.com> <5495be36.6153c20a.04b7.ffff864b@mx.google.com>, Message-ID: <5495db8e.4a6ab40a.0636.ffff97c7@mx.google.com> I?m not proposing any particular translation scheme, I?ll leave that to more capable people :) Obviously there has to be one, but I?m coming to this from point of view of how an end-user would be interacting with and using that translation scheme from their code. -- Have a nice day, Timo. Sent from Windows Mail From: Ali Ebrahimi Sent: ?Saturday?, ?December? ?20?, ?2014 ?19?:?36 To: Timo Kinnunen Cc: valhalla-dev at openjdk.java.net what is your translation scheme for specialization? is that Brian's Or ... I'm confused, from your response T instantiated as ?valuable? int not int? I'm correct? On Sat, Dec 20, 2014 at 9:41 PM, Timo Kinnunen wrote: It is int, so you end up with two methods in the API which both take the same type and a need to distinguish between them somehow. This is analogous to the BigList example from the previous email. There the problem was about choosing between one method taking a normal BigInteger and another taking an ?erasable? BigInteger. Here the problem is about choosing between one method taking a plain int and another method taking a ?valuable? int. -- Have a nice day, Timo. Sent from Windows Mail From: Ali Ebrahimi Sent: ?Saturday?, ?December? ?20?, ?2014 ?19?:?04 To: Timo Kinnunen Cc: valhalla-dev at openjdk.java.net What is instantiated type var for T in List? Integer or int On Sat, Dec 20, 2014 at 3:54 PM, Timo Kinnunen wrote: Here an anyfied List version and a demo: interface List { public void remove(int position); public void remove(T element); static void test(List list) { // calls remove(int position); list.remove((int) 3); // calls remove(T element); list.remove(3); } } The choice of which method to prefer with the plain, cast-less version is somewhat arbitrary. My rationale for preferring it like this rather than the other way around is that the specialized type is more interesting. Thus the compiler should make calling methods taking one as easy as possible. -- Have a nice day, Timo. Sent from Windows Mail From: Ali Ebrahimi Sent: ?Saturday?, ?December? ?20?, ?2014 ?0?:?53 To: Timo Kinnunen Cc: Brian Goetz, valhalla-dev at openjdk.java.net As long as I know, we currently have List and We try to specialize (or any-fy) that. How your solution handle List case? On Sat, Dec 20, 2014 at 2:15 AM, Timo Kinnunen wrote: Hi, I?m not sure Peeling is necessary. The reason is that the problem it?s trying to solve already exists in the current Java and it has workarounds too. Here?s a demonstration with three ListLike adaptations and the workarounds: interface SmallList { public void remove(short position); public void remove(T element); } interface MediumList { public void remove(int position); public void remove(T element); } interface BigList { public void remove(BigInteger position); public void remove(T element); } public class Workaround { @SuppressWarnings({ "rawtypes", "unchecked" }) static void method(SmallList smallList, MediumList mediumList, BigList bigList) { smallList.remove((short) 3); smallList.remove((Short) (short) 3); mediumList.remove(3); mediumList.remove((Integer) 3); ((BigList) bigList).remove(BigInteger.valueOf(3)); ((BigList) bigList).remove((Object) BigInteger.valueOf(3)); } } For the record, none of the workarounds feel ?correct? to me, although the int/Integer pair gets close. Rather than Peeling, what I think is needed is to streamline overload selection so that the specialized methods are selected whenever possible and the non-specialized methods can be manually selected with extra casts, like this: smallList.remove((short) 3); smallList.remove(3); mediumList.remove((int) 3); mediumList.remove(3); bigList.remove((BigInteger) BigInteger.valueOf(3)); bigList.remove(BigInteger.valueOf(3)); -- Have a nice day, Timo. Sent from Windows Mail From: Brian Goetz Sent: ?Friday?, ?December? ?19?, ?2014 ?22?:?31 To: valhalla-dev at openjdk.java.net I've updated the State of the Specialization here: http://cr.openjdk.java.net/~briangoetz/valhalla/specialization.html The old version is here: http://cr.openjdk.java.net/~briangoetz/valhalla/specialization-1.html From ali.ebrahimi1781 at gmail.com Sat Dec 20 21:30:56 2014 From: ali.ebrahimi1781 at gmail.com (Ali Ebrahimi) Date: Sun, 21 Dec 2014 01:00:56 +0330 Subject: Updated State of the Specialization In-Reply-To: <5495db8e.4a6ab40a.0636.ffff97c7@mx.google.com> References: <5494993C.8000509@oracle.com> <5494afc0.a266b40a.4df0.ffff9672@mx.google.com> <54956e40.d38ec20a.7ade.2ef1@mx.google.com> <5495be36.6153c20a.04b7.ffff864b@mx.google.com> <5495db8e.4a6ab40a.0636.ffff97c7@mx.google.com> Message-ID: So we assume there is such scheme (ideal world). M concerns is with primitive types and main goal of all efforts is avoiding boxing/un-boxing. And you not answered my second question, I'm asking this again: T instantiated as ?valuable? int or int in List? and what is signature of (generated) generic version of remove method in corresponding bytecode? On Sat, Dec 20, 2014 at 11:52 PM, Timo Kinnunen wrote: > I?m not proposing any particular translation scheme, I?ll leave that to > more capable people :) Obviously there has to be one, but I?m coming to > this from point of view of how an end-user would be interacting with and > using that translation scheme from their code. > > > > > -- > Have a nice day, > Timo. > > Sent from Windows Mail > > *From:* Ali Ebrahimi > *Sent:* ?Saturday?, ?December? ?20?, ?2014 ?19?:?36 > > *To:* Timo Kinnunen > *Cc:* valhalla-dev at openjdk.java.net > > what is your translation scheme for specialization? is that Brian's Or ... > I'm confused, from your response T instantiated as ?valuable? int not int? > I'm correct? > > On Sat, Dec 20, 2014 at 9:41 PM, Timo Kinnunen > wrote: > >> It is int, so you end up with two methods in the API which both take >> the same type and a need to distinguish between them somehow. >> >> This is analogous to the BigList example from the previous >> email. There the problem was about choosing between one method taking a >> normal BigInteger and another taking an ?erasable? BigInteger. >> >> Here the problem is about choosing between one method taking a plain int >> and another method taking a ?valuable? int. >> >> >> >> >> -- >> Have a nice day, >> Timo. >> >> Sent from Windows Mail >> >> *From:* Ali Ebrahimi >> *Sent:* ?Saturday?, ?December? ?20?, ?2014 ?19?:?04 >> *To:* Timo Kinnunen >> *Cc:* valhalla-dev at openjdk.java.net >> >> What is instantiated type var for T in List? Integer or int >> >> On Sat, Dec 20, 2014 at 3:54 PM, Timo Kinnunen >> wrote: >> >>> Here an anyfied List version and a demo: >>> >>> interface List { >>> public void remove(int position); >>> public void remove(T element); >>> >>> static void test(List list) { >>> >>> // calls remove(int position); >>> list.remove((int) 3); >>> >>> // calls remove(T element); >>> list.remove(3); >>> } >>> } >>> >>> The choice of which method to prefer with the plain, cast-less version >>> is somewhat arbitrary. My rationale for preferring it like this rather than >>> the other way around is that the specialized type is more interesting. Thus >>> the compiler should make calling methods taking one as easy as possible. >>> >>> -- >>> Have a nice day, >>> Timo. >>> >>> Sent from Windows Mail >>> >>> *From:* Ali Ebrahimi >>> *Sent:* ?Saturday?, ?December? ?20?, ?2014 ?0?:?53 >>> *To:* Timo Kinnunen >>> *Cc:* Brian Goetz , >>> valhalla-dev at openjdk.java.net >>> >>> As long as I know, we currently have List and We try to specialize >>> (or any-fy) that. >>> How your solution handle List case? >>> >>> >>> On Sat, Dec 20, 2014 at 2:15 AM, Timo Kinnunen >>> wrote: >>>> >>>> Hi, >>>> >>>> >>>> I?m not sure Peeling is necessary. The reason is that the problem it?s >>>> trying to solve already exists in the current Java and it has workarounds >>>> too. Here?s a demonstration with three ListLike adaptations and the >>>> workarounds: >>>> >>>> >>>> interface SmallList { >>>> >>>> public void remove(short position); >>>> >>>> public void remove(T element); >>>> >>>> } >>>> >>>> interface MediumList { >>>> >>>> public void remove(int position); >>>> >>>> public void remove(T element); >>>> >>>> } >>>> >>>> interface BigList { >>>> >>>> public void remove(BigInteger position); >>>> >>>> public void remove(T element); >>>> >>>> } >>>> >>>> >>>> public class Workaround { >>>> >>>> @SuppressWarnings({ "rawtypes", "unchecked" }) >>>> >>>> static void method(SmallList smallList, MediumList >>>> mediumList, BigList bigList) { >>>> >>>> >>>> smallList.remove((short) 3); >>>> >>>> smallList.remove((Short) (short) 3); >>>> >>>> >>>> mediumList.remove(3); >>>> >>>> mediumList.remove((Integer) 3); >>>> >>>> >>>> ((BigList) bigList).remove(BigInteger.valueOf(3)); >>>> >>>> ((BigList) bigList).remove((Object) BigInteger.valueOf(3)); >>>> >>>> } >>>> >>>> } >>>> >>>> >>>> For the record, none of the workarounds feel ?correct? to me, although >>>> the int/Integer pair gets close. >>>> >>>> >>>> Rather than Peeling, what I think is needed is to streamline overload >>>> selection so that the specialized methods are selected whenever possible >>>> and the non-specialized methods can be manually selected with extra casts, >>>> like this: >>>> >>>> >>>> >>>> smallList.remove((short) 3); >>>> >>>> smallList.remove(3); >>>> >>>> >>>> >>>> >>>> mediumList.remove((int) 3); >>>> >>>> mediumList.remove(3); >>>> >>>> >>>> >>>> >>>> bigList.remove((BigInteger) BigInteger.valueOf(3)); >>>> >>>> bigList.remove(BigInteger.valueOf(3)); >>>> >>>> >>>> >>>> >>>> -- >>>> Have a nice day, >>>> Timo. >>>> >>>> Sent from Windows Mail >>>> >>>> >>>> >>>> >>>> >>>> From: Brian Goetz >>>> Sent: ?Friday?, ?December? ?19?, ?2014 ?22?:?31 >>>> To: valhalla-dev at openjdk.java.net >>>> >>>> >>>> >>>> >>>> >>>> I've updated the State of the Specialization here: >>>> http://cr.openjdk.java.net/~briangoetz/valhalla/specialization.html >>>> >>>> The old version is here: >>>> >>>> http://cr.openjdk.java.net/~briangoetz/valhalla/specialization-1.html >>>> >>> >> > From ali.ebrahimi1781 at gmail.com Sat Dec 20 22:05:35 2014 From: ali.ebrahimi1781 at gmail.com (Ali Ebrahimi) Date: Sun, 21 Dec 2014 01:35:35 +0330 Subject: Updated State of the Specialization In-Reply-To: <5495db8e.4a6ab40a.0636.ffff97c7@mx.google.com> References: <5494993C.8000509@oracle.com> <5494afc0.a266b40a.4df0.ffff9672@mx.google.com> <54956e40.d38ec20a.7ade.2ef1@mx.google.com> <5495be36.6153c20a.04b7.ffff864b@mx.google.com> <5495db8e.4a6ab40a.0636.ffff97c7@mx.google.com> Message-ID: Ah I forget to say, your proposed workaround is not compatible with current java generics. consider following example: class Foo{ void bar(String s){} void bar(T s){} } Foo foo = new Foo(); foo.bar((String)"Test"); //fails to compile foo.bar((Object)"Test");//fails to compile foo.bar("Test");//fails to compile Is this a bug or feature? echoing Brain......... On Sat, Dec 20, 2014 at 11:52 PM, Timo Kinnunen wrote: > I?m not proposing any particular translation scheme, I?ll leave that to > more capable people :) Obviously there has to be one, but I?m coming to > this from point of view of how an end-user would be interacting with and > using that translation scheme from their code. > > > > > -- > Have a nice day, > Timo. > > Sent from Windows Mail > > *From:* Ali Ebrahimi > *Sent:* ?Saturday?, ?December? ?20?, ?2014 ?19?:?36 > > *To:* Timo Kinnunen > *Cc:* valhalla-dev at openjdk.java.net > > what is your translation scheme for specialization? is that Brian's Or ... > I'm confused, from your response T instantiated as ?valuable? int not int? > I'm correct? > > On Sat, Dec 20, 2014 at 9:41 PM, Timo Kinnunen > wrote: > >> It is int, so you end up with two methods in the API which both take >> the same type and a need to distinguish between them somehow. >> >> This is analogous to the BigList example from the previous >> email. There the problem was about choosing between one method taking a >> normal BigInteger and another taking an ?erasable? BigInteger. >> >> Here the problem is about choosing between one method taking a plain int >> and another method taking a ?valuable? int. >> >> >> >> >> -- >> Have a nice day, >> Timo. >> >> Sent from Windows Mail >> >> *From:* Ali Ebrahimi >> *Sent:* ?Saturday?, ?December? ?20?, ?2014 ?19?:?04 >> *To:* Timo Kinnunen >> *Cc:* valhalla-dev at openjdk.java.net >> >> What is instantiated type var for T in List? Integer or int >> >> On Sat, Dec 20, 2014 at 3:54 PM, Timo Kinnunen >> wrote: >> >>> Here an anyfied List version and a demo: >>> >>> interface List { >>> public void remove(int position); >>> public void remove(T element); >>> >>> static void test(List list) { >>> >>> // calls remove(int position); >>> list.remove((int) 3); >>> >>> // calls remove(T element); >>> list.remove(3); >>> } >>> } >>> >>> The choice of which method to prefer with the plain, cast-less version >>> is somewhat arbitrary. My rationale for preferring it like this rather than >>> the other way around is that the specialized type is more interesting. Thus >>> the compiler should make calling methods taking one as easy as possible. >>> >>> -- >>> Have a nice day, >>> Timo. >>> >>> Sent from Windows Mail >>> >>> *From:* Ali Ebrahimi >>> *Sent:* ?Saturday?, ?December? ?20?, ?2014 ?0?:?53 >>> *To:* Timo Kinnunen >>> *Cc:* Brian Goetz , >>> valhalla-dev at openjdk.java.net >>> >>> As long as I know, we currently have List and We try to specialize >>> (or any-fy) that. >>> How your solution handle List case? >>> >>> >>> On Sat, Dec 20, 2014 at 2:15 AM, Timo Kinnunen >>> wrote: >>>> >>>> Hi, >>>> >>>> >>>> I?m not sure Peeling is necessary. The reason is that the problem it?s >>>> trying to solve already exists in the current Java and it has workarounds >>>> too. Here?s a demonstration with three ListLike adaptations and the >>>> workarounds: >>>> >>>> >>>> interface SmallList { >>>> >>>> public void remove(short position); >>>> >>>> public void remove(T element); >>>> >>>> } >>>> >>>> interface MediumList { >>>> >>>> public void remove(int position); >>>> >>>> public void remove(T element); >>>> >>>> } >>>> >>>> interface BigList { >>>> >>>> public void remove(BigInteger position); >>>> >>>> public void remove(T element); >>>> >>>> } >>>> >>>> >>>> public class Workaround { >>>> >>>> @SuppressWarnings({ "rawtypes", "unchecked" }) >>>> >>>> static void method(SmallList smallList, MediumList >>>> mediumList, BigList bigList) { >>>> >>>> >>>> smallList.remove((short) 3); >>>> >>>> smallList.remove((Short) (short) 3); >>>> >>>> >>>> mediumList.remove(3); >>>> >>>> mediumList.remove((Integer) 3); >>>> >>>> >>>> ((BigList) bigList).remove(BigInteger.valueOf(3)); >>>> >>>> ((BigList) bigList).remove((Object) BigInteger.valueOf(3)); >>>> >>>> } >>>> >>>> } >>>> >>>> >>>> For the record, none of the workarounds feel ?correct? to me, although >>>> the int/Integer pair gets close. >>>> >>>> >>>> Rather than Peeling, what I think is needed is to streamline overload >>>> selection so that the specialized methods are selected whenever possible >>>> and the non-specialized methods can be manually selected with extra casts, >>>> like this: >>>> >>>> >>>> >>>> smallList.remove((short) 3); >>>> >>>> smallList.remove(3); >>>> >>>> >>>> >>>> >>>> mediumList.remove((int) 3); >>>> >>>> mediumList.remove(3); >>>> >>>> >>>> >>>> >>>> bigList.remove((BigInteger) BigInteger.valueOf(3)); >>>> >>>> bigList.remove(BigInteger.valueOf(3)); >>>> >>>> >>>> >>>> >>>> -- >>>> Have a nice day, >>>> Timo. >>>> >>>> Sent from Windows Mail >>>> >>>> >>>> >>>> >>>> >>>> From: Brian Goetz >>>> Sent: ?Friday?, ?December? ?19?, ?2014 ?22?:?31 >>>> To: valhalla-dev at openjdk.java.net >>>> >>>> >>>> >>>> >>>> >>>> I've updated the State of the Specialization here: >>>> http://cr.openjdk.java.net/~briangoetz/valhalla/specialization.html >>>> >>>> The old version is here: >>>> >>>> http://cr.openjdk.java.net/~briangoetz/valhalla/specialization-1.html >>>> >>> >> > From timo.kinnunen at gmail.com Sat Dec 20 22:18:35 2014 From: timo.kinnunen at gmail.com (=?utf-8?Q?Timo_Kinnunen?=) Date: Sat, 20 Dec 2014 22:18:35 +0000 Subject: =?utf-8?Q?Re:_Updated_State_of_the_Specialization?= In-Reply-To: References: <5494993C.8000509@oracle.com> <5494afc0.a266b40a.4df0.ffff9672@mx.google.com> <54956e40.d38ec20a.7ade.2ef1@mx.google.com> <5495be36.6153c20a.04b7.ffff864b@mx.google.com> <5495db8e.4a6ab40a.0636.ffff97c7@mx.google.com>, Message-ID: <5495f66e.6360b40a.5908.ffffb560@mx.google.com> The workaround works if you do it like this: class Foo{ void bar(String s){ System.out.println(1); } void bar(T s){ System.out.println(2); } public static void main(String... args) { Foo foo = new Foo(); ((Foo) foo).bar("Test"); ((Foo)foo).bar((Object)"Test"); } } (Yes, it?s a dirty workaround?) Hope this helps. -- Have a nice day, Timo. Sent from Windows Mail From: Ali Ebrahimi Sent: ?Saturday?, ?December? ?20?, ?2014 ?23?:?05 To: Timo Kinnunen, Brian Goetz Cc: valhalla-dev at openjdk.java.net Ah I forget to say, your proposed workaround is not compatible with current java generics. consider following example: class Foo{ void bar(String s){} void bar(T s){} } Foo foo = new Foo(); foo.bar((String)"Test"); //fails to compile foo.bar((Object)"Test");//fails to compile foo.bar("Test");//fails to compile Is this a bug or feature? echoing Brain......... On Sat, Dec 20, 2014 at 11:52 PM, Timo Kinnunen wrote: I?m not proposing any particular translation scheme, I?ll leave that to more capable people :) Obviously there has to be one, but I?m coming to this from point of view of how an end-user would be interacting with and using that translation scheme from their code. -- Have a nice day, Timo. Sent from Windows Mail From: Ali Ebrahimi Sent: ?Saturday?, ?December? ?20?, ?2014 ?19?:?36 To: Timo Kinnunen Cc: valhalla-dev at openjdk.java.net what is your translation scheme for specialization? is that Brian's Or ... I'm confused, from your response T instantiated as ?valuable? int not int? I'm correct? On Sat, Dec 20, 2014 at 9:41 PM, Timo Kinnunen wrote: It is int, so you end up with two methods in the API which both take the same type and a need to distinguish between them somehow. This is analogous to the BigList example from the previous email. There the problem was about choosing between one method taking a normal BigInteger and another taking an ?erasable? BigInteger. Here the problem is about choosing between one method taking a plain int and another method taking a ?valuable? int. -- Have a nice day, Timo. Sent from Windows Mail From: Ali Ebrahimi Sent: ?Saturday?, ?December? ?20?, ?2014 ?19?:?04 To: Timo Kinnunen Cc: valhalla-dev at openjdk.java.net What is instantiated type var for T in List? Integer or int On Sat, Dec 20, 2014 at 3:54 PM, Timo Kinnunen wrote: Here an anyfied List version and a demo: interface List { public void remove(int position); public void remove(T element); static void test(List list) { // calls remove(int position); list.remove((int) 3); // calls remove(T element); list.remove(3); } } The choice of which method to prefer with the plain, cast-less version is somewhat arbitrary. My rationale for preferring it like this rather than the other way around is that the specialized type is more interesting. Thus the compiler should make calling methods taking one as easy as possible. -- Have a nice day, Timo. Sent from Windows Mail From: Ali Ebrahimi Sent: ?Saturday?, ?December? ?20?, ?2014 ?0?:?53 To: Timo Kinnunen Cc: Brian Goetz, valhalla-dev at openjdk.java.net As long as I know, we currently have List and We try to specialize (or any-fy) that. How your solution handle List case? On Sat, Dec 20, 2014 at 2:15 AM, Timo Kinnunen wrote: Hi, I?m not sure Peeling is necessary. The reason is that the problem it?s trying to solve already exists in the current Java and it has workarounds too. Here?s a demonstration with three ListLike adaptations and the workarounds: interface SmallList { public void remove(short position); public void remove(T element); } interface MediumList { public void remove(int position); public void remove(T element); } interface BigList { public void remove(BigInteger position); public void remove(T element); } public class Workaround { @SuppressWarnings({ "rawtypes", "unchecked" }) static void method(SmallList smallList, MediumList mediumList, BigList bigList) { smallList.remove((short) 3); smallList.remove((Short) (short) 3); mediumList.remove(3); mediumList.remove((Integer) 3); ((BigList) bigList).remove(BigInteger.valueOf(3)); ((BigList) bigList).remove((Object) BigInteger.valueOf(3)); } } For the record, none of the workarounds feel ?correct? to me, although the int/Integer pair gets close. Rather than Peeling, what I think is needed is to streamline overload selection so that the specialized methods are selected whenever possible and the non-specialized methods can be manually selected with extra casts, like this: smallList.remove((short) 3); smallList.remove(3); mediumList.remove((int) 3); mediumList.remove(3); bigList.remove((BigInteger) BigInteger.valueOf(3)); bigList.remove(BigInteger.valueOf(3)); -- Have a nice day, Timo. Sent from Windows Mail From: Brian Goetz Sent: ?Friday?, ?December? ?19?, ?2014 ?22?:?31 To: valhalla-dev at openjdk.java.net I've updated the State of the Specialization here: http://cr.openjdk.java.net/~briangoetz/valhalla/specialization.html The old version is here: http://cr.openjdk.java.net/~briangoetz/valhalla/specialization-1.html From timo.kinnunen at gmail.com Sat Dec 20 22:22:05 2014 From: timo.kinnunen at gmail.com (=?utf-8?Q?Timo_Kinnunen?=) Date: Sat, 20 Dec 2014 22:22:05 +0000 Subject: =?utf-8?Q?Re:_Updated_State_of_the_Specialization?= In-Reply-To: References: <5494993C.8000509@oracle.com> <5494afc0.a266b40a.4df0.ffff9672@mx.google.com> <54956e40.d38ec20a.7ade.2ef1@mx.google.com> <5495be36.6153c20a.04b7.ffff864b@mx.google.com> <5495db8e.4a6ab40a.0636.ffff97c7@mx.google.com>, Message-ID: <5495f9a5.614cc20a.63e8.ffffc160@mx.google.com> ?valuable? int. As for the signature of the generated generic version in bytecode, I have no preference. Perhaps (4)V to mean that the method takes 4 bytes of ?valuable? data as its first argument and returns no value?? I really don?t know what?s good or bad here. -- Have a nice day, Timo. Sent from Windows Mail From: Ali Ebrahimi Sent: ?Saturday?, ?December? ?20?, ?2014 ?22?:?30 To: Timo Kinnunen Cc: valhalla-dev at openjdk.java.net So we assume there is such scheme (ideal world). M concerns is with primitive types and main goal of all efforts is avoiding boxing/un-boxing. And you not answered my second question, I'm asking this again: T instantiated as ?valuable? int or int in List? and what is signature of (generated) generic version of remove method in corresponding bytecode? On Sat, Dec 20, 2014 at 11:52 PM, Timo Kinnunen wrote: I?m not proposing any particular translation scheme, I?ll leave that to more capable people :) Obviously there has to be one, but I?m coming to this from point of view of how an end-user would be interacting with and using that translation scheme from their code. -- Have a nice day, Timo. Sent from Windows Mail From: Ali Ebrahimi Sent: ?Saturday?, ?December? ?20?, ?2014 ?19?:?36 To: Timo Kinnunen Cc: valhalla-dev at openjdk.java.net what is your translation scheme for specialization? is that Brian's Or ... I'm confused, from your response T instantiated as ?valuable? int not int? I'm correct? On Sat, Dec 20, 2014 at 9:41 PM, Timo Kinnunen wrote: It is int, so you end up with two methods in the API which both take the same type and a need to distinguish between them somehow. This is analogous to the BigList example from the previous email. There the problem was about choosing between one method taking a normal BigInteger and another taking an ?erasable? BigInteger. Here the problem is about choosing between one method taking a plain int and another method taking a ?valuable? int. -- Have a nice day, Timo. Sent from Windows Mail From: Ali Ebrahimi Sent: ?Saturday?, ?December? ?20?, ?2014 ?19?:?04 To: Timo Kinnunen Cc: valhalla-dev at openjdk.java.net What is instantiated type var for T in List? Integer or int On Sat, Dec 20, 2014 at 3:54 PM, Timo Kinnunen wrote: Here an anyfied List version and a demo: interface List { public void remove(int position); public void remove(T element); static void test(List list) { // calls remove(int position); list.remove((int) 3); // calls remove(T element); list.remove(3); } } The choice of which method to prefer with the plain, cast-less version is somewhat arbitrary. My rationale for preferring it like this rather than the other way around is that the specialized type is more interesting. Thus the compiler should make calling methods taking one as easy as possible. -- Have a nice day, Timo. Sent from Windows Mail From: Ali Ebrahimi Sent: ?Saturday?, ?December? ?20?, ?2014 ?0?:?53 To: Timo Kinnunen Cc: Brian Goetz, valhalla-dev at openjdk.java.net As long as I know, we currently have List and We try to specialize (or any-fy) that. How your solution handle List case? On Sat, Dec 20, 2014 at 2:15 AM, Timo Kinnunen wrote: Hi, I?m not sure Peeling is necessary. The reason is that the problem it?s trying to solve already exists in the current Java and it has workarounds too. Here?s a demonstration with three ListLike adaptations and the workarounds: interface SmallList { public void remove(short position); public void remove(T element); } interface MediumList { public void remove(int position); public void remove(T element); } interface BigList { public void remove(BigInteger position); public void remove(T element); } public class Workaround { @SuppressWarnings({ "rawtypes", "unchecked" }) static void method(SmallList smallList, MediumList mediumList, BigList bigList) { smallList.remove((short) 3); smallList.remove((Short) (short) 3); mediumList.remove(3); mediumList.remove((Integer) 3); ((BigList) bigList).remove(BigInteger.valueOf(3)); ((BigList) bigList).remove((Object) BigInteger.valueOf(3)); } } For the record, none of the workarounds feel ?correct? to me, although the int/Integer pair gets close. Rather than Peeling, what I think is needed is to streamline overload selection so that the specialized methods are selected whenever possible and the non-specialized methods can be manually selected with extra casts, like this: smallList.remove((short) 3); smallList.remove(3); mediumList.remove((int) 3); mediumList.remove(3); bigList.remove((BigInteger) BigInteger.valueOf(3)); bigList.remove(BigInteger.valueOf(3)); -- Have a nice day, Timo. Sent from Windows Mail From: Brian Goetz Sent: ?Friday?, ?December? ?19?, ?2014 ?22?:?31 To: valhalla-dev at openjdk.java.net I've updated the State of the Specialization here: http://cr.openjdk.java.net/~briangoetz/valhalla/specialization.html The old version is here: http://cr.openjdk.java.net/~briangoetz/valhalla/specialization-1.html From ali.ebrahimi1781 at gmail.com Sat Dec 20 22:58:19 2014 From: ali.ebrahimi1781 at gmail.com (Ali Ebrahimi) Date: Sun, 21 Dec 2014 02:28:19 +0330 Subject: Updated State of the Specialization In-Reply-To: <5495f66e.6360b40a.5908.ffffb560@mx.google.com> References: <5494993C.8000509@oracle.com> <5494afc0.a266b40a.4df0.ffff9672@mx.google.com> <54956e40.d38ec20a.7ade.2ef1@mx.google.com> <5495be36.6153c20a.04b7.ffff864b@mx.google.com> <5495db8e.4a6ab40a.0636.ffff97c7@mx.google.com> <5495f66e.6360b40a.5908.ffffb560@mx.google.com> Message-ID: I don't think this is workaround, maybe anti-workaround! If you want bypass java's generic type system, just don't use it. Foo foo = new Foo(); foo.bar("Test"); foo.bar((Object)"Test"); On Sun, Dec 21, 2014 at 1:48 AM, Timo Kinnunen wrote: > The workaround works if you do it like this: > > class Foo{ > void bar(String s){ System.out.println(1); } > void bar(T s){ System.out.println(2); } > > public static void main(String... args) { > Foo foo = new Foo(); > ((Foo) foo).bar("Test"); > ((Foo)foo).bar((Object)"Test"); > } > } > > (Yes, it?s a dirty workaround?) > > Hope this helps. > > > > -- > Have a nice day, > Timo. > > Sent from Windows Mail > > *From:* Ali Ebrahimi > *Sent:* ?Saturday?, ?December? ?20?, ?2014 ?23?:?05 > *To:* Timo Kinnunen , Brian Goetz > > *Cc:* valhalla-dev at openjdk.java.net > > Ah I forget to say, your proposed workaround is not compatible with > current java generics. consider following example: > class Foo{ > void bar(String s){} > void bar(T s){} > } > > Foo foo = new Foo(); > foo.bar((String)"Test"); //fails to compile > foo.bar((Object)"Test");//fails to compile > foo.bar("Test");//fails to compile > > Is this a bug or feature? echoing Brain......... > > > On Sat, Dec 20, 2014 at 11:52 PM, Timo Kinnunen > wrote: > >> I?m not proposing any particular translation scheme, I?ll leave that to >> more capable people :) Obviously there has to be one, but I?m coming to >> this from point of view of how an end-user would be interacting with and >> using that translation scheme from their code. >> >> >> >> >> -- >> Have a nice day, >> Timo. >> >> Sent from Windows Mail >> >> *From:* Ali Ebrahimi >> *Sent:* ?Saturday?, ?December? ?20?, ?2014 ?19?:?36 >> >> *To:* Timo Kinnunen >> *Cc:* valhalla-dev at openjdk.java.net >> >> what is your translation scheme for specialization? is that Brian's Or ... >> I'm confused, from your response T instantiated as ?valuable? int not >> int? I'm correct? >> >> On Sat, Dec 20, 2014 at 9:41 PM, Timo Kinnunen >> wrote: >> >>> It is int, so you end up with two methods in the API which both take >>> the same type and a need to distinguish between them somehow. >>> >>> This is analogous to the BigList example from the previous >>> email. There the problem was about choosing between one method taking a >>> normal BigInteger and another taking an ?erasable? BigInteger. >>> >>> Here the problem is about choosing between one method taking a plain int >>> and another method taking a ?valuable? int. >>> >>> >>> >>> >>> -- >>> Have a nice day, >>> Timo. >>> >>> Sent from Windows Mail >>> >>> *From:* Ali Ebrahimi >>> *Sent:* ?Saturday?, ?December? ?20?, ?2014 ?19?:?04 >>> *To:* Timo Kinnunen >>> *Cc:* valhalla-dev at openjdk.java.net >>> >>> What is instantiated type var for T in List? Integer or int >>> >>> On Sat, Dec 20, 2014 at 3:54 PM, Timo Kinnunen >>> wrote: >>> >>>> Here an anyfied List version and a demo: >>>> >>>> interface List { >>>> public void remove(int position); >>>> public void remove(T element); >>>> >>>> static void test(List list) { >>>> >>>> // calls remove(int position); >>>> list.remove((int) 3); >>>> >>>> // calls remove(T element); >>>> list.remove(3); >>>> } >>>> } >>>> >>>> The choice of which method to prefer with the plain, cast-less version >>>> is somewhat arbitrary. My rationale for preferring it like this rather than >>>> the other way around is that the specialized type is more interesting. Thus >>>> the compiler should make calling methods taking one as easy as possible. >>>> >>>> -- >>>> Have a nice day, >>>> Timo. >>>> >>>> Sent from Windows Mail >>>> >>>> *From:* Ali Ebrahimi >>>> *Sent:* ?Saturday?, ?December? ?20?, ?2014 ?0?:?53 >>>> *To:* Timo Kinnunen >>>> *Cc:* Brian Goetz , >>>> valhalla-dev at openjdk.java.net >>>> >>>> As long as I know, we currently have List and We try to specialize >>>> (or any-fy) that. >>>> How your solution handle List case? >>>> >>>> >>>> On Sat, Dec 20, 2014 at 2:15 AM, Timo Kinnunen >>> > wrote: >>>>> >>>>> Hi, >>>>> >>>>> >>>>> I?m not sure Peeling is necessary. The reason is that the problem it?s >>>>> trying to solve already exists in the current Java and it has workarounds >>>>> too. Here?s a demonstration with three ListLike adaptations and the >>>>> workarounds: >>>>> >>>>> >>>>> interface SmallList { >>>>> >>>>> public void remove(short position); >>>>> >>>>> public void remove(T element); >>>>> >>>>> } >>>>> >>>>> interface MediumList { >>>>> >>>>> public void remove(int position); >>>>> >>>>> public void remove(T element); >>>>> >>>>> } >>>>> >>>>> interface BigList { >>>>> >>>>> public void remove(BigInteger position); >>>>> >>>>> public void remove(T element); >>>>> >>>>> } >>>>> >>>>> >>>>> public class Workaround { >>>>> >>>>> @SuppressWarnings({ "rawtypes", "unchecked" }) >>>>> >>>>> static void method(SmallList smallList, MediumList >>>>> mediumList, BigList bigList) { >>>>> >>>>> >>>>> smallList.remove((short) 3); >>>>> >>>>> smallList.remove((Short) (short) 3); >>>>> >>>>> >>>>> mediumList.remove(3); >>>>> >>>>> mediumList.remove((Integer) 3); >>>>> >>>>> >>>>> ((BigList) bigList).remove(BigInteger.valueOf(3)); >>>>> >>>>> ((BigList) bigList).remove((Object) BigInteger.valueOf(3)); >>>>> >>>>> } >>>>> >>>>> } >>>>> >>>>> >>>>> For the record, none of the workarounds feel ?correct? to me, although >>>>> the int/Integer pair gets close. >>>>> >>>>> >>>>> Rather than Peeling, what I think is needed is to streamline overload >>>>> selection so that the specialized methods are selected whenever possible >>>>> and the non-specialized methods can be manually selected with extra casts, >>>>> like this: >>>>> >>>>> >>>>> >>>>> smallList.remove((short) 3); >>>>> >>>>> smallList.remove(3); >>>>> >>>>> >>>>> >>>>> >>>>> mediumList.remove((int) 3); >>>>> >>>>> mediumList.remove(3); >>>>> >>>>> >>>>> >>>>> >>>>> bigList.remove((BigInteger) BigInteger.valueOf(3)); >>>>> >>>>> bigList.remove(BigInteger.valueOf(3)); >>>>> >>>>> >>>>> >>>>> >>>>> -- >>>>> Have a nice day, >>>>> Timo. >>>>> >>>>> Sent from Windows Mail >>>>> >>>>> >>>>> >>>>> >>>>> >>>>> From: Brian Goetz >>>>> Sent: ?Friday?, ?December? ?19?, ?2014 ?22?:?31 >>>>> To: valhalla-dev at openjdk.java.net >>>>> >>>>> >>>>> >>>>> >>>>> >>>>> I've updated the State of the Specialization here: >>>>> http://cr.openjdk.java.net/~briangoetz/valhalla/specialization.html >>>>> >>>>> The old version is here: >>>>> >>>>> http://cr.openjdk.java.net/~briangoetz/valhalla/specialization-1.html >>>>> >>>> >>> >> > From brian.goetz at oracle.com Sun Dec 21 03:25:56 2014 From: brian.goetz at oracle.com (Brian Goetz) Date: Sat, 20 Dec 2014 22:25:56 -0500 Subject: Updated State of the Specialization In-Reply-To: <5495C896.7070103@ochsenreither.de> References: <5494993C.8000509@oracle.com> <564593832.47313.1419039855813.JavaMail.open-xchange@srv005.service.ps-server.net> <5494E23C.3070009@oracle.com> <5495C896.7070103@ochsenreither.de> Message-ID: <54963DC4.4070302@oracle.com> > Imho, a real fix would be to provide an alternative method which works > better, not to introduce a huge language feature to work around one > method. I don't want to imagine how the JVM/Java will look like if you > add language feature work-arounds for every case of poor API design. Which is exactly what the Map.get example in the document proposes; migrate the API to a better place, while retaining migration compatibility with the billions of lines of outstanding code. But it needs some language help to retain compatibility. I think this may be the actual point of contention here; it seems you're willing to inflict incompatibility on the user base for the sake of progress. That's a fine strategy when you have no users / your users are all bleeding-edge adopters / you hate your users. Unfortunately none of these are the case for us...so we have to do better. That said, you've made your point, which is "I think this is a bigger hammer than is needed." And you may well be right. And once we're convinced the hammer offers the right degree of impulse delivery, we'll look for simplifications. But we can't throw compatibility under the bus. > (If or how the syntax will work in Java is not my main interest here. > What matters is the bytecode. There were also a few ideas in the past to > wrap this idiom in a "nicer" API like def default[T] = > null.asInstanceOf[T] in Scala, but considering that a) the use of zero > values is not that high b) null.asInstanceOf[T] works fine as an idiom, > no further action was taken.) This is all based on the way we reify hitherto-erased type information, though the BytecodeMapping attribute. This gives us back the generic (not-erased) signature -- in a standard classfile signature format -- of the type. If you did something like: void foo() { ... T.default ... // please, don't comment on the syntax } the erased bytecode still has a aconst_null, but the BytecodeMapping attribute has a signature of TT;, so at specialization time, we'd specialize the aconst_null bytecode to the appropriate type (e.g., iconst_0). > With the introduction of value types there needs to be a way to achieve > this in bytecode, because an approach where you first check for every > primitive type and return null otherwise just doesn't work with > user-definable value types. We've not yet settled on whether user-defined value types can define their own default value, or whether they just get "all fields initialized to their default value". The latter is certainly simpler, but either way, there's a path to specializing the aconst_null to this (e.g., invoke no-arg "constructor".) >> Here's another example, then: the problem of "Maps from int to int" is >> a well-studied special case, with many clever implementation tricks >> that are not available to more general-purpose maps. > That's certainly a better example! I'm not sure whether creating the > chance of having subtle behavioral differences between different > collection instantiations is an acceptable price to pay for that, though. Fair question. On the other hand, its not clear that ruling it out without considering it is prudent either. From twhitmore.nz at gmail.com Sun Dec 21 06:11:01 2014 From: twhitmore.nz at gmail.com (Thomas W) Date: Sun, 21 Dec 2014 19:11:01 +1300 Subject: valhalla-dev Digest, Vol 6, Issue 3 In-Reply-To: References: Message-ID: Hi everybody, Hi Brian, Appreciate the draft. I'm going to largely agree with Simon Ochsenreither on the merits of simplicity -- I'm dubious about layering/peeling -- and add a few suggestions of my own. 1) List.remove() disambiguation ----------------------------------------------------- We can easily disambiguate the remove() methods by annotation; adding a longer "specific" name. Thus: @Disambiguate("removeAt") public T remove (int index); @Disambiguate("removeItem") public boolean remove (T item); // traditionally, item is Object; could specify this as 'compatible' Compiler & specializer would thus be able to generate bridge methods, from the "ambiguous" signature to the unambiguous method. Syntax could work either way around -- renaming the methods now & annotating the old "ambigous" name would be better engineering, but less source-compatible. Type specification of 'item' could be a solved problem, or a specific type syntax could be introduced to handle this. "compatible" could possibly be a reasonable keyword to express the intent; Object was originally considered "compatible with" T, but for a value-type T only T would be compatible. Not sure that we'd want to turn "compatible" into a keyword generally, though, as it could be quite widely used as a variable name. 2) List.remove() cleaner syntax --------------------------------------------- - everybody hates java.util.Enumeration and it's gratuitously over-long syntax, - so let's use List.removeAt(int index), List.removeItem(T item) etc. 3) "Empty" values -------------------------- - as somebody pointed out, we need a syntax that references 'empty' values by type; null or zero. - I propose 'T.empty' for this purpose; eg, int.empty references 0, Object.empty references null. 4) Map.get() and "sentinel values" -------------------------------------------------------- - null is a moderately good "sentinel value" for objects, but zero is not so good for numbers; - similar to the 'T.empty' syntax proposed above, I propose a 'T.sentinel' syntax for "no element". eg, int.sentinel references -1, Object.sentinel references null. 5) Statics; synchronizing to access these? ---------------------------------------------------------------- - good point about SomeType and SomeType sharing the same statics; - but since they do not have class in common, what syntax/ or common object can they synchronize on? - possible proposal: T.classLock, which should be the base Class (but perhaps just typed as Object). 6) Equals, esp. null-safe! -------------------------------------- - comparing objects (especially in a null-safe way) is a fundamental operation of Collections etc. - if we prohibit null-checks, we cannot write such code! - if we allow null-checks & specialize them for value-types to NOP, we allow other possibly wrong uses of 'null' to remain. As a side rant: - null-safety has required stupid & ugly code in Java for so long. Every library has had to write this, whereas the base library should have done it once, and done it right, back a version 1.1. Nor is "null as a monad" (Optional in Java 8) the good basic solution we need. - and where are Optional.equals( nullableX, nullableY) and Optional.hashCode( nullableX) methods??? - I called my null-handling class "Optional" back at Java 5. Now some dropkick comes along and pollutes my namespace with these poorly-thought-out & incomplete FP ideas. We're not Scala, let's not pretend to be. Coming back to the problem at hand: we're not going to use Monads for null-safe equality, we don't have rocks in our heads, but we do want a type-portable null-safe equals(). - do we want to consider T.equals(x, y) ?? - any better ideas?? 7) Peeling and Layers -------------------------------- - these ideas seem major & complex, but solve only relatively moderate corner cases. - introducing a major new structural level into the Java language, breaking long-standing single Java types into separate parts is an enormous change; seemingly suitable for "mixins" or some really major language enhancement. - yet the parts/layers are not named/ or addressible, and the use of this structure will really be quite minor. Summary: introducing a banner-level language feature to solve two problematic methods, with no other possible use, does not really seem the right design choice. 8) Conclusions ---------------------- Introduction of a simple "field-style" syntax on types extends the existing usage of ".class", to allow important new type-related expressions to be expressed in an easy & obvious way. It also gives minimal potential for conflict with existing syntax. I am much happier to avoid cast-based formulations, such as casting 'null' to int, to get zeros/nulls in a type-specific way. Introducing a well-defined syntax for "empty" and "sentinel" values could resolve most no-item & empty-value problems -- which is where null & null problems typically crop up -- in an effective manner. I absolutely think we need a type-specific method/ or syntax for null-safe equals; this is a basic to writing most collections code. However, I'm less clear on what "the right" syntax should be here. Any takers? Look forward to your thoughts, Regards Thomas Whitmore From simon at ochsenreither.de Sun Dec 21 15:14:03 2014 From: simon at ochsenreither.de (Simon Ochsenreither) Date: Sun, 21 Dec 2014 16:14:03 +0100 Subject: Updated State of the Specialization In-Reply-To: <54963DC4.4070302@oracle.com> References: <5494993C.8000509@oracle.com> <564593832.47313.1419039855813.JavaMail.open-xchange@srv005.service.ps-server.net> <5494E23C.3070009@oracle.com> <5495C896.7070103@ochsenreither.de> <54963DC4.4070302@oracle.com> Message-ID: <5496E3BB.6080408@ochsenreither.de> > Which is exactly what the Map.get example in the document proposes; > migrate the API to a better place, while retaining migration > compatibility with the billions of lines of outstanding code. On this we agree. > But it needs some language help to retain compatibility. That's the thing I'm skeptic about. > I think this may be the actual point of contention here; it seems > you're willing to inflict incompatibility on the user base for the > sake of progress. Absolutely not! Everything I suggest is intended to be compatible. I think the point of contention is that the draft proposes a really complicated way to "disable" inconvenient methods like Map#get for value types, and I don't believe that a) it is absolutely necessary to disable those methods and b) the complexity is worth it to achieve this goal. If we start doctoring Map#get and List#remove, what does this draft have in store for java.util.Date and java.util.Calendar? My earlier suggestion to just keep inconvenient methods around is even _more_ compatible for people doing the migration, than selectively disabling such methods. If you want to steer people away from those methods, add a @DeprecatedForValueTypes annotation, let the compiler emit a warning and be done. > We've not yet settled on whether user-defined value types can define > their own default value, How will this work if you have e. g. an Array of value-type T ... will you go through the whole array and initialize it to the default value after allocation? Or require extra bits to track which elements have been initialized already? > or whether they just get "all fields initialized to their default > value". The latter is certainly simpler, but either way, there's a > path to specializing the aconst_null to this (e.g., invoke no-arg > "constructor".) So there are 3+ different ways to do it now? Depending on whether you are in specialized or erased code and whether you have references, primitives or value types? From brian.goetz at oracle.com Sun Dec 21 15:31:31 2014 From: brian.goetz at oracle.com (Brian Goetz) Date: Sun, 21 Dec 2014 10:31:31 -0500 Subject: Updated State of the Specialization In-Reply-To: <5496E3BB.6080408@ochsenreither.de> References: <5494993C.8000509@oracle.com> <564593832.47313.1419039855813.JavaMail.open-xchange@srv005.service.ps-server.net> <5494E23C.3070009@oracle.com> <5495C896.7070103@ochsenreither.de> <54963DC4.4070302@oracle.com> <5496E3BB.6080408@ochsenreither.de> Message-ID: <5496E7D3.2060808@oracle.com> >> We've not yet settled on whether user-defined value types can define >> their own default value, > How will this work if you have e. g. an Array of value-type T ... will > you go through the whole array and initialize it to the default value > after allocation? Or require extra bits to track which elements have > been initialized already? Which is exactly why we are wary of the "user-defined default value" feature -- even though nearly everyone who reads the value-type proposal in some depth suggests it as a desirable feature within the first few hours. It is a feature that seems very attractive from the "here's the source code I want to write" perspective, but challenging from the "how does the VM implement it efficiently" perspective. From gustav.r.akesson at gmail.com Sun Dec 21 15:54:24 2014 From: gustav.r.akesson at gmail.com (=?UTF-8?Q?Gustav_=C3=85kesson?=) Date: Sun, 21 Dec 2014 16:54:24 +0100 Subject: Updated State of the Specialization In-Reply-To: <5494993C.8000509@oracle.com> References: <5494993C.8000509@oracle.com> Message-ID: Hi, I'm going through the nitty-gritty details of this super exciting proposal, but one question came to mind which I couldn't find an explanation for in the proposal. If we have... class Summerizer { int sumHashCodes(T ... entries) { // Sum hash code values for all entries using ::hashCode() } } ...then how will the specialized class for Summerizer know that the same semantics as Integer::hashCode() should be inferred here? Same goes for the other primitive types. I'm thinking of e.g. equals as well. Using synchronized on the type could be prohibited (as stated by the Language restriction section), but what above methods inherited from Object? Best Regards, Gustav ?kesson On Fri, Dec 19, 2014 at 10:31 PM, Brian Goetz wrote: > I've updated the State of the Specialization here: > http://cr.openjdk.java.net/~briangoetz/valhalla/specialization.html > > The old version is here: > http://cr.openjdk.java.net/~briangoetz/valhalla/specialization-1.html > > From brian.goetz at oracle.com Sun Dec 21 16:07:28 2014 From: brian.goetz at oracle.com (Brian Goetz) Date: Sun, 21 Dec 2014 11:07:28 -0500 Subject: Updated State of the Specialization In-Reply-To: References: <5494993C.8000509@oracle.com> Message-ID: <5496F040.7090208@oracle.com> Value types need to have some form of at least some of the core Object methods, at least hashCode, equals, and toString. Open questions here include: - Will there be some interface that specifies these? (C# has a root interfaces like this that all structs implement) - Will Object implement that interface? (Seems nice for generic code, but then it can't be called anything Value-ish, would have to be called Object-ish, like "Objectionable" or "Objectifiable" or "ObjectionYourHonor".) The compiler or VM would certainly generate default implementations of equals/hashCode that delegates to the components. A further open question is whether these could be overridden by value types, or whether this is just part of their definition. (And, if equals/hashCode are effectively final, its a little weird for toString to be standing alone, though would be permissible.) On 12/21/2014 10:54 AM, Gustav ?kesson wrote: > Hi, > > I'm going through the nitty-gritty details of this super exciting > proposal, but one question came to mind which I couldn't find an > explanation for in the proposal. If we have... > > > class Summerizer { > > int sumHashCodes(T ... entries) { > > // Sum hash code values for all entries using ::hashCode() > > } > > } > > ...then how will the specialized class for Summerizer know that the > same semantics as Integer::hashCode() should be inferred here? Same goes > for the other primitive types. > > I'm thinking of e.g. equals as well. Using synchronized on the type > could be prohibited (as stated by the Language restriction section), but > what above methods inherited from Object? > > > Best Regards, > > Gustav ?kesson > > > On Fri, Dec 19, 2014 at 10:31 PM, Brian Goetz > wrote: > > I've updated the State of the Specialization here: > http://cr.openjdk.java.net/~__briangoetz/valhalla/__specialization.html > > > The old version is here: > http://cr.openjdk.java.net/~__briangoetz/valhalla/__specialization-1.html > > > From brian.goetz at oracle.com Sun Dec 21 16:47:25 2014 From: brian.goetz at oracle.com (Brian Goetz) Date: Sun, 21 Dec 2014 11:47:25 -0500 Subject: valhalla-dev Digest, Vol 6, Issue 3 In-Reply-To: References: Message-ID: <5496F99D.3060107@oracle.com> > 1) List.remove() disambiguation Your solution here amounts to a deprecation mechanism with hints, which is an OK solution to the remove(int)/remove(Object) problem. (I'm a little mystified, though, how everyone seem to assume that the remove overload conflict is the only problem that Peeling addresses itself to, and if somehow that one could be solved, the whole rest of the exercise is pointless.) What's your story for the Collection method removeAll(Collection) in such a way that a removeAll method could be called from generic code like: removeAllFrom(Collection originalCollection, Collection eltsToRemove) { ... } > 3) "Empty" values > -------------------------- > - as somebody pointed out, we need a syntax that references 'empty' values > by type; null or zero. > - I propose 'T.empty' for this purpose; eg, int.empty references 0, > Object.empty references null. Minus ten points for digressing into syntax. There are infinitely many possibly syntaxes for this, and they *all* will be suggested eventually, but unfortunately such discussions have a tendency to choke off actual useful discourse. Right now, we're figuring out the right model, and there's more than enough work to do there. > 4) Map.get() and "sentinel values" > -------------------------------------------------------- > - null is a moderately good "sentinel value" for objects, but zero is not > so good for numbers; > - similar to the 'T.empty' syntax proposed above, I propose a 'T.sentinel' > syntax for "no element". > eg, int.sentinel references -1, Object.sentinel references null. The reason int can't be null is that we have no natural and efficient hardware representation for it; all 2^32 values in an 32-bit integer are used for integers. So changing the syntax from "null" to "sentinel" doesn't help -- the real problem is, how do we represent it? Ballooning all integers to 64 bits just to accommodate a special value is not going to fly. And stealing "-1" as the "not to be used as an int" value similarly doesn't fly; -1 is also an important integer. Applications and APIs are free to cut corners like "let's let -1 mean 'no value'", but languages and VMs are not free to do this. And, minus ten points more for another syntax digression :) > 5) Statics; synchronizing to access these? > ---------------------------------------------------------------- > - good point about SomeType and SomeType sharing the > same statics; > - but since they do not have class in common, what syntax/ or common object > can they synchronize on? > - possible proposal: T.classLock, which should be the base Class (but > perhaps just typed as Object). Agree that being able to denote "the class that hosts my static members" is desirable. Syntax can wait. > - I called my null-handling class "Optional" back at Java 5. Now some > dropkick comes along and pollutes my namespace with these > poorly-thought-out & incomplete FP ideas. Thanks, I was that dropkick. > 7) Peeling and Layers > -------------------------------- > - these ideas seem major & complex, but solve only relatively moderate > corner cases. I think you're giving them too much weight, perhaps because they're new and scary. These are not intended to be, to use your term, a "banner" feature; our hope would be that they almost never get used. And yes, they currently have a lot of surface. See separate note on the subject. > - introducing a major new structural level into the Java language, breaking > long-standing single Java types into separate parts is an enormous change; > seemingly suitable for "mixins" or some really major language enhancement. > - yet the parts/layers are not named/ or addressible, and the use of this > structure will really be quite minor. > > Summary: introducing a banner-level language feature to solve two > problematic methods, with no other possible use, does not really seem the > right design choice. > > > 8) Conclusions > ---------------------- > > Introduction of a simple "field-style" syntax on types extends the existing > usage of ".class", to allow important new type-related expressions to be > expressed in an easy & obvious way. It also gives minimal potential for > conflict with existing syntax. > > I am much happier to avoid cast-based formulations, such as casting 'null' > to int, to get zeros/nulls in a type-specific way. Introducing a > well-defined syntax for "empty" and "sentinel" values could resolve most > no-item & empty-value problems -- which is where null & null problems > typically crop up -- in an effective manner. > > I absolutely think we need a type-specific method/ or syntax for null-safe > equals; this is a basic to writing most collections code. However, I'm > less clear on what "the right" syntax should be here. Any takers? > > Look forward to your thoughts, > > Regards > Thomas Whitmore > From brian.goetz at oracle.com Sun Dec 21 16:57:03 2014 From: brian.goetz at oracle.com (Brian Goetz) Date: Sun, 21 Dec 2014 11:57:03 -0500 Subject: "Bleah, Layers are too complicated!" (was: Updated State of the Specialization) In-Reply-To: <5496E3BB.6080408@ochsenreither.de> References: <5494993C.8000509@oracle.com> <564593832.47313.1419039855813.JavaMail.open-xchange@srv005.service.ps-server.net> <5494E23C.3070009@oracle.com> <5495C896.7070103@ochsenreither.de> <54963DC4.4070302@oracle.com> <5496E3BB.6080408@ochsenreither.de> Message-ID: <5496FBDF.4070906@oracle.com> I can understand why everyone is inclined to jump all over layers as being "too complicated"; we have our own concerns there too, which I think we've been honest about. But, you're all getting ahead of yourselves; it feels like you're having a collective panic attack of "OMG, they're going to kill Java with complexity, so I'd better freak out." So everyone ... relax. Right now, we're still *figuring out the problems* (which includes separating the real problems from the perceived ones). The one thing I know is that the final solution will almost certainly look very different. (Everyone says they want us to work more openly, rather than emerging from our cave with the final answer -- but you have to do your part by showing some awareness that what we're sharing is work-in-progress.) We've only thought about these issues for maybe a thousand hours so far; that's not enough to get a good answer to hard problems like this. So *of course* the solutions we've got so far are half-baked. How could they be anything else? Until we fully understand the problems, we are going to focus on the theoretical characteristics of the possible solution, how well it solves the problem, and how the solutions fit in with how the language actually works (i.e., the type system, overload selection, method dispatch, etc). The fact that it looms too large in the user model or the syntax is weird or has a lot of surface for what feels like corner cases can't be our top priority now; focusing on the surface aspects distracts from figuring out whether we're even on the right track or not. Now, it's common that the solutions one ends up with after the first or second or third round is still more complicated than you'd like, so then begins the agonizing slow process of peeling back perceived requirements in order to simplify how the solutions fit into the user perception of the language. It seems that people want to "help" by jumping right to that end stage by saying "this problem isn't important to solve". But unexamined opinions of which problems can be punted on is not really that helpful to us. The thoughts we're sharing are very much work in progress. Please engage accordingly; at this stage, constructive help looks like generating better understanding of the problems. From forax at univ-mlv.fr Sun Dec 21 18:06:14 2014 From: forax at univ-mlv.fr (Remi Forax) Date: Sun, 21 Dec 2014 19:06:14 +0100 Subject: "Bleah, Layers are too complicated!" In-Reply-To: <5496FBDF.4070906@oracle.com> References: <5494993C.8000509@oracle.com> <564593832.47313.1419039855813.JavaMail.open-xchange@srv005.service.ps-server.net> <5494E23C.3070009@oracle.com> <5495C896.7070103@ochsenreither.de> <54963DC4.4070302@oracle.com> <5496E3BB.6080408@ochsenreither.de> <5496FBDF.4070906@oracle.com> Message-ID: <54970C16.70107@univ-mlv.fr> The layer concept is not too far from the C++ class specialization concept. Clearly, it's better IMO than the selector (the where clause) from the previous draft because you can express that a specialization use different fields/type of fields. Now, I think 'specialization' is a better term and 'ref' is not needed because it's the dual of 'any', and I think i prefer to repeat all type variables (and their constraints). |interface Map { V getOrDefault(K key, V defaultValue); specialization Map { V get(K key); default V getOrDefault(K key, V defaultValue) { return containsKey(key) ? get(key) : defaultValue; } } }| || Specialization is nevertheless complex but I think the syntax above is more Java-ish. cheers, R?mi On 12/21/2014 05:57 PM, Brian Goetz wrote: > I can understand why everyone is inclined to jump all over layers as > being "too complicated"; we have our own concerns there too, which I > think we've been honest about. But, you're all getting ahead of > yourselves; it feels like you're having a collective panic attack of > "OMG, they're going to kill Java with complexity, so I'd better freak > out." > > So everyone ... relax. > > Right now, we're still *figuring out the problems* (which includes > separating the real problems from the perceived ones). The one thing > I know is that the final solution will almost certainly look very > different. (Everyone says they want us to work more openly, rather > than emerging from our cave with the final answer -- but you have to > do your part by showing some awareness that what we're sharing is > work-in-progress.) > > We've only thought about these issues for maybe a thousand hours so > far; that's not enough to get a good answer to hard problems like > this. So *of course* the solutions we've got so far are half-baked. > How could they be anything else? > > Until we fully understand the problems, we are going to focus on the > theoretical characteristics of the possible solution, how well it > solves the problem, and how the solutions fit in with how the language > actually works (i.e., the type system, overload selection, method > dispatch, etc). The fact that it looms too large in the user model or > the syntax is weird or has a lot of surface for what feels like corner > cases can't be our top priority now; focusing on the surface aspects > distracts from figuring out whether we're even on the right track or not. > > Now, it's common that the solutions one ends up with after the first > or second or third round is still more complicated than you'd like, so > then begins the agonizing slow process of peeling back perceived > requirements in order to simplify how the solutions fit into the user > perception of the language. It seems that people want to "help" by > jumping right to that end stage by saying "this problem isn't > important to solve". But unexamined opinions of which problems can be > punted on is not really that helpful to us. > > The thoughts we're sharing are very much work in progress. Please > engage accordingly; at this stage, constructive help looks like > generating better understanding of the problems. > > From peter.levart at gmail.com Mon Dec 22 01:08:09 2014 From: peter.levart at gmail.com (Peter Levart) Date: Mon, 22 Dec 2014 02:08:09 +0100 Subject: valhalla-dev Digest, Vol 6, Issue 3 In-Reply-To: <5496F99D.3060107@oracle.com> References: <5496F99D.3060107@oracle.com> Message-ID: <54976EF9.7000702@gmail.com> On 12/21/2014 05:47 PM, Brian Goetz wrote: >> 4) Map.get() and "sentinel values" >> -------------------------------------------------------- >> - null is a moderately good "sentinel value" for objects, but zero is >> not >> so good for numbers; >> - similar to the 'T.empty' syntax proposed above, I propose a >> 'T.sentinel' >> syntax for "no element". >> eg, int.sentinel references -1, Object.sentinel references null. > > The reason int can't be null is that we have no natural and efficient > hardware representation for it; all 2^32 values in an 32-bit integer > are used for integers. So changing the syntax from "null" to > "sentinel" doesn't help -- the real problem is, how do we represent > it? Ballooning all integers to 64 bits just to accommodate a special > value is not going to fly. And stealing "-1" as the "not to be used > as an int" value similarly doesn't fly; -1 is also an important integer. > > Applications and APIs are free to cut corners like "let's let -1 mean > 'no value'", but languages and VMs are not free to do this. Hi, What happened to Optional? If Optional could be morphed into a value type AND be specialized at the same time, then returning Optional from Map.getOptionaly(k) would be the right thing to do. Peter. From brian.goetz at oracle.com Mon Dec 22 01:18:08 2014 From: brian.goetz at oracle.com (Brian Goetz) Date: Sun, 21 Dec 2014 20:18:08 -0500 Subject: valhalla-dev Digest, Vol 6, Issue 3 In-Reply-To: <54976EF9.7000702@gmail.com> References: <5496F99D.3060107@oracle.com> <54976EF9.7000702@gmail.com> Message-ID: <54977150.5060602@oracle.com> > Hi, > > What happened to Optional? > > If Optional could be morphed into a value type AND be specialized at the > same time, then returning Optional from Map.getOptionaly(k) > would be the right thing to do. Nothing has happened yet! But, it is high on the list of nice-to-haves to have a path to migrating a value-based reference class to be a value type. Significant challenges exist on this path, but we're going to try anyway. A value-Optional would indeed provide one path forward for rehabilitating Map.get. (The existing getOrDefault is another option.) From lovro.pandzic at gmail.com Mon Dec 22 09:48:54 2014 From: lovro.pandzic at gmail.com (Lovro Pandzic) Date: Mon, 22 Dec 2014 10:48:54 +0100 Subject: Value types and parameter names Message-ID: > > The counterpart of a "setFoo" method for an immutable class would be "withFoo": > > final __ByValue class Point { > public final int x, y; > public Point(int x, int y) { this.x = x; this.y = y; } > public Point withX(int x1) { return new Point(x1, y); } > public Point withY(int y1) { return new Point(x, y1); } > } > > I think the same clunky tricks as can be done for "setters" can also be done for "with-ers". > > (Word note: "wither" has unpleasant connotations compared to "setter". A setter is a nice dog, a wether is a sad goat.) > > The awkwardness of working with "with-er" methods is well-known. For example, in a paper I was just browsing: > > I guess for value types this wouldn't incur any significant cost as it would for objects. My personal preference is to use constructors if it is possible and acceptable in terms of readability, but "with-ers" are a nice alternative. Anyone know the answer for > On the side note, is there an option to get classes with the JDK with > parameter names? (like String, Integer, etc) > > Lovro Pand?i? From peter.levart at gmail.com Mon Dec 22 10:00:04 2014 From: peter.levart at gmail.com (Peter Levart) Date: Mon, 22 Dec 2014 11:00:04 +0100 Subject: Updated State of the Specialization In-Reply-To: <5496F040.7090208@oracle.com> References: <5494993C.8000509@oracle.com> <5496F040.7090208@oracle.com> Message-ID: <5497EBA4.9040706@gmail.com> On 12/21/2014 05:07 PM, Brian Goetz wrote: > Value types need to have some form of at least some of the core Object > methods, at least hashCode, equals, and toString. Open questions here > include: > > - Will there be some interface that specifies these? (C# has a root > interfaces like this that all structs implement) > - Will Object implement that interface? (Seems nice for generic > code, but then it can't be called anything Value-ish, would have to be > called Object-ish, like "Objectionable" or "Objectifiable" or > "ObjectionYourHonor".) > > The compiler or VM would certainly generate default implementations of > equals/hashCode that delegates to the components. A further open > question is whether these could be overridden by value types, or > whether this is just part of their definition. (And, if > equals/hashCode are effectively final, its a little weird for toString > to be standing alone, though would be permissible.) I think default .equals() method for value types should be the bit-wise compare of all fields. I think this is a very important canonical equals and hard to implement in custom method easily (because of peculiarities of float and double). Like default equals for reference types, it is an equivalence relation with the greatest possible number of equivalence classes. The default .hashCode() method could then be some quick bit-wise sum of public fields. If there are no public fields, it would simply be 0. Value types holding sensitive information would then have to contain some public uniquifying field if they wanted to be used as keys in hash maps or implement a secure hash algorithm if they hold enough entropy. Regards, Peter From david.r.chase at oracle.com Mon Dec 22 15:08:19 2014 From: david.r.chase at oracle.com (David Chase) Date: Mon, 22 Dec 2014 10:08:19 -0500 Subject: Updated State of the Specialization In-Reply-To: <5497EBA4.9040706@gmail.com> References: <5494993C.8000509@oracle.com> <5496F040.7090208@oracle.com> <5497EBA4.9040706@gmail.com> Message-ID: On 2014-12-22, at 5:00 AM, Peter Levart wrote: > On 12/21/2014 05:07 PM, Brian Goetz wrote: >> Value types need to have some form of at least some of the core Object methods, at least hashCode, equals, and toString. Open questions here include: >> >> - Will there be some interface that specifies these? (C# has a root interfaces like this that all structs implement) >> - Will Object implement that interface? (Seems nice for generic code, but then it can't be called anything Value-ish, would have to be called Object-ish, like "Objectionable" or "Objectifiable" or "ObjectionYourHonor".) >> >> The compiler or VM would certainly generate default implementations of equals/hashCode that delegates to the components. A further open question is whether these could be overridden by value types, or whether this is just part of their definition. (And, if equals/hashCode are effectively final, its a little weird for toString to be standing alone, though would be permissible.) > > I think default .equals() method for value types should be the bit-wise compare of all fields. I think this is a very important canonical equals and hard to implement in custom method easily (because of peculiarities of float and double). > Like default equals for reference types, it is an equivalence relation with the greatest possible number of equivalence classes. The default .hashCode() method could then be some quick bit-wise sum of public fields. If there are no public fields, it would simply be 0. Value types holding sensitive information would then have to contain some public uniquifying field if they wanted to be used as keys in hash maps or implement a secure hash algorithm if they hold enough entropy. Could we be a little bit less excited about "quick" and a little bit more excited about the quality of the hashcode? My one worry is whether we go for the reproducible hashcode that makes DOS slightly more possible but yields reproducible results for testing and debugging, versus a "VM's choice" version of hashcode with constants that vary from run to run that would thwart DOS. I'm also tempted to say that hashcodes should include private fields but be overrideable, so anyone needing true privacy would redefine hashcode and hopefully someone competent would implement it. Including private fields and using a decent hash function means that by default we probably get a better hashcode than your average programmer (or James Gosling) would implement. Also, in the state-of-the-specialization document, 1,$s/top-of-static/top-of-stack/ Someone's fingers were a little too well trained. David From brian.goetz at oracle.com Mon Dec 22 15:58:16 2014 From: brian.goetz at oracle.com (Brian Goetz) Date: Mon, 22 Dec 2014 10:58:16 -0500 Subject: Updated State of the Specialization In-Reply-To: <5497EBA4.9040706@gmail.com> References: <5494993C.8000509@oracle.com> <5496F040.7090208@oracle.com> <5497EBA4.9040706@gmail.com> Message-ID: <54983F98.2000206@oracle.com> You're on the right track, but I think bitwise is the wrong answer; I think the right answer is applying == componentwise. Otherwise, if I have a value type: value class DoubleHolder { double val; } DoubleHolder d1 = "new" DoubleHolder(NaN); DoubleHolder d2 = "new" DoubleHolder(NaN); Under a componentwise ==, I get d1 != d2, just as I would with two double values, but under a bitwise, I get d1 == d2. This is exactly the asymmetry I think you're trying to avoid! Better to apply the rule that two values are == iff all their components are ==. But you say "default equals()". Do you think this should be overridable? Or should this just be what == means, just as it does for int? > I think default .equals() method for value types should be the bit-wise > compare of all fields. I think this is a very important canonical equals > and hard to implement in custom method easily (because of peculiarities > of float and double). Like default equals for reference types, it is an > equivalence relation with the greatest possible number of equivalence > classes. The default .hashCode() method could then be some quick > bit-wise sum of public fields. If there are no public fields, it would > simply be 0. Value types holding sensitive information would then have > to contain some public uniquifying field if they wanted to be used as > keys in hash maps or implement a secure hash algorithm if they hold > enough entropy. > > Regards, Peter From sproket at videotron.ca Mon Dec 22 20:00:12 2014 From: sproket at videotron.ca (Dan Howard) Date: Mon, 22 Dec 2014 15:00:12 -0500 Subject: value class convention Message-ID: <5498784C.7060003@videotron.ca> Question what does the following C# code output: class Program { static void Main(string[] args) { Account account =new Account(); account.AcccountNumber ="1234"; account.Name ="Savings"; account.Balance = 10; Console.WriteLine("BEFORE: " + account); adjustAccountBalance(account, 10); Console.WriteLine("AFTER: " + account); Console.ReadLine(); } static void adjustAccountBalance(Account account,float balance) { account.Balance += balance; } } Answer: *unknown.* Since we don't know if an Account is a *class *or a *struct*. One way would could help avoid this situation in Java would be to use lower case/underscore convention for value types - to give same indication as primitives. Here we'd have: account account =new account(); or point p =new point(); etc.. What do you think? --- This email has been checked for viruses by Avast antivirus software. http://www.avast.com From timo.kinnunen at gmail.com Mon Dec 22 19:59:45 2014 From: timo.kinnunen at gmail.com (=?utf-8?Q?Timo_Kinnunen?=) Date: Mon, 22 Dec 2014 19:59:45 +0000 Subject: =?utf-8?Q?Re:_valhalla-dev_Digest,_Vol_6,_Issue_3?= In-Reply-To: <5496F99D.3060107@oracle.com> References: , <5496F99D.3060107@oracle.com> Message-ID: <54987b1f.0f0db50a.1ecf.381a@mx.google.com> Regarding ?What's your story for the Collection method removeAll(Collection) in such a way that a removeAll method could be called from generic code like: removeAllFrom(Collection originalCollection, Collection eltsToRemove) { ... }?: What is the format that an accepted answer should be presented in? Here?s one answer, but I don?t know if that?s what you?re looking for: static <@NonNull U> boolean removeAllFrom(Set<@NonNull U> originalCollection, Collection eltsToRemove) { if(eltsToRemove == null) { throw new NullPointerException(); } boolean modified = false; if(originalCollection.map.size() > eltsToRemove.size()) { for(Iterator i = eltsToRemove.iterator(); i.hasNext();) { @NonNull U next = i.next(); // boxing conversion of "next" if HashMap.remove(Object) is not any-fied modified |= originalCollection.map.remove(next) == Set.PRESENT; } } else { for(Iterator<@NonNull U> i = originalCollection.map.keySet().iterator(); i.hasNext();) { @NonNull U next = i.next(); // boxing conversion of "next" if Collection.remove(Object) is not any-fied if(eltsToRemove.contains(next)) { i.remove(); modified = true; } } } return modified; } (Feel free to replace @NonNull with the any keyword if you like) That?s the implementation from a HashSet point-of-view after inlining calls to other HashSet instance methods and one static method from Objects. I see two places where a value type may need to be boxed depending on whether the method that?s being called is ?any-aware?. Is this what you?re looking for? -- Have a nice day, Timo. Sent from Windows Mail From: Brian Goetz Sent: ?Sunday?, ?December? ?21?, ?2014 ?17?:?47 To: Thomas W, valhalla-dev at openjdk.java.net, simon at ochsenreither.de > 1) List.remove() disambiguation Your solution here amounts to a deprecation mechanism with hints, which is an OK solution to the remove(int)/remove(Object) problem. (I'm a little mystified, though, how everyone seem to assume that the remove overload conflict is the only problem that Peeling addresses itself to, and if somehow that one could be solved, the whole rest of the exercise is pointless.) What's your story for the Collection method removeAll(Collection) in such a way that a removeAll method could be called from generic code like: removeAllFrom(Collection originalCollection, Collection eltsToRemove) { ... } > 3) "Empty" values > -------------------------- > - as somebody pointed out, we need a syntax that references 'empty' values > by type; null or zero. > - I propose 'T.empty' for this purpose; eg, int.empty references 0, > Object.empty references null. Minus ten points for digressing into syntax. There are infinitely many possibly syntaxes for this, and they *all* will be suggested eventually, but unfortunately such discussions have a tendency to choke off actual useful discourse. Right now, we're figuring out the right model, and there's more than enough work to do there. > 4) Map.get() and "sentinel values" > -------------------------------------------------------- > - null is a moderately good "sentinel value" for objects, but zero is not > so good for numbers; > - similar to the 'T.empty' syntax proposed above, I propose a 'T.sentinel' > syntax for "no element". > eg, int.sentinel references -1, Object.sentinel references null. The reason int can't be null is that we have no natural and efficient hardware representation for it; all 2^32 values in an 32-bit integer are used for integers. So changing the syntax from "null" to "sentinel" doesn't help -- the real problem is, how do we represent it? Ballooning all integers to 64 bits just to accommodate a special value is not going to fly. And stealing "-1" as the "not to be used as an int" value similarly doesn't fly; -1 is also an important integer. Applications and APIs are free to cut corners like "let's let -1 mean 'no value'", but languages and VMs are not free to do this. And, minus ten points more for another syntax digression :) > 5) Statics; synchronizing to access these? > ---------------------------------------------------------------- > - good point about SomeType and SomeType sharing the > same statics; > - but since they do not have class in common, what syntax/ or common object > can they synchronize on? > - possible proposal: T.classLock, which should be the base Class (but > perhaps just typed as Object). Agree that being able to denote "the class that hosts my static members" is desirable. Syntax can wait. > - I called my null-handling class "Optional" back at Java 5. Now some > dropkick comes along and pollutes my namespace with these > poorly-thought-out & incomplete FP ideas. Thanks, I was that dropkick. > 7) Peeling and Layers > -------------------------------- > - these ideas seem major & complex, but solve only relatively moderate > corner cases. I think you're giving them too much weight, perhaps because they're new and scary. These are not intended to be, to use your term, a "banner" feature; our hope would be that they almost never get used. And yes, they currently have a lot of surface. See separate note on the subject. > - introducing a major new structural level into the Java language, breaking > long-standing single Java types into separate parts is an enormous change; > seemingly suitable for "mixins" or some really major language enhancement. > - yet the parts/layers are not named/ or addressible, and the use of this > structure will really be quite minor. > > Summary: introducing a banner-level language feature to solve two > problematic methods, with no other possible use, does not really seem the > right design choice. > > > 8) Conclusions > ---------------------- > > Introduction of a simple "field-style" syntax on types extends the existing > usage of ".class", to allow important new type-related expressions to be > expressed in an easy & obvious way. It also gives minimal potential for > conflict with existing syntax. > > I am much happier to avoid cast-based formulations, such as casting 'null' > to int, to get zeros/nulls in a type-specific way. Introducing a > well-defined syntax for "empty" and "sentinel" values could resolve most > no-item & empty-value problems -- which is where null & null problems > typically crop up -- in an effective manner. > > I absolutely think we need a type-specific method/ or syntax for null-safe > equals; this is a basic to writing most collections code. However, I'm > less clear on what "the right" syntax should be here. Any takers? > > Look forward to your thoughts, > > Regards > Thomas Whitmore > From simon at ochsenreither.de Mon Dec 22 20:18:48 2014 From: simon at ochsenreither.de (Simon Ochsenreither) Date: Mon, 22 Dec 2014 21:18:48 +0100 Subject: value class convention In-Reply-To: <5498784C.7060003@videotron.ca> References: <5498784C.7060003@videotron.ca> Message-ID: <54987CA8.4080902@ochsenreither.de> > Answer: *unknown.* Since we don't know if an Account is a *class *or a > *struct*. Answer in Java: *known*, because value types are immutable. From sproket at videotron.ca Mon Dec 22 23:12:31 2014 From: sproket at videotron.ca (Dan Howard) Date: Mon, 22 Dec 2014 18:12:31 -0500 Subject: value class convention In-Reply-To: <54987CA8.4080902@ochsenreither.de> References: <5498784C.7060003@videotron.ca> <54987CA8.4080902@ochsenreither.de> Message-ID: <5498A55F.8030303@videotron.ca> Thanks. Very happy to hear that! :) On 12/22/2014 3:18 PM, Simon Ochsenreither wrote: >> Answer: *unknown.* Since we don't know if an Account is a *class *or >> a *struct*. > Answer in Java: *known*, because value types are immutable. > --- This email has been checked for viruses by Avast antivirus software. http://www.avast.com From simon at ochsenreither.de Tue Dec 23 17:10:22 2014 From: simon at ochsenreither.de (Simon Ochsenreither) Date: Tue, 23 Dec 2014 18:10:22 +0100 Subject: value class convention In-Reply-To: <5498A55F.8030303@videotron.ca> References: <5498784C.7060003@videotron.ca> <54987CA8.4080902@ochsenreither.de> <5498A55F.8030303@videotron.ca> Message-ID: <5499A1FE.9080106@ochsenreither.de> > Thanks. Very happy to hear that! :) You're welcome. :-) From peter.levart at gmail.com Thu Dec 25 17:01:20 2014 From: peter.levart at gmail.com (Peter Levart) Date: Thu, 25 Dec 2014 18:01:20 +0100 Subject: Updated State of the Specialization In-Reply-To: <54983F98.2000206@oracle.com> References: <5494993C.8000509@oracle.com> <5496F040.7090208@oracle.com> <5497EBA4.9040706@gmail.com> <54983F98.2000206@oracle.com> Message-ID: <549C42E0.3080508@gmail.com> On 12/22/2014 04:58 PM, Brian Goetz wrote: > You're on the right track, but I think bitwise is the wrong answer; I > think the right answer is applying == componentwise. Otherwise, if I > have a value type: > > value class DoubleHolder { > double val; > } > > DoubleHolder d1 = "new" DoubleHolder(NaN); > DoubleHolder d2 = "new" DoubleHolder(NaN); > > Under a componentwise ==, I get d1 != d2, just as I would with two > double values, but under a bitwise, I get d1 == d2. This is exactly > the asymmetry I think you're trying to avoid! Better to apply the > rule that two values are == iff all their components are ==. > The problem with double '==' is that it is not an equivalence relation (because of NaN value). And I think .equals() should be or some value types would be unsuitable for use as keys in hash maps. java.lang.Double.equals() does bitwise comparison for the same reason. Perhaps an '==' operator could be defined for value types as component-wise '=='. It's just that default .equals() would not be the same as '==' for all value types then. > But you say "default equals()". Do you think this should be > overridable? Or should this just be what == means, just as it does > for int? This would not really be overriding in the sense of virtual methods. Javac could generate default equals()/hashCode() methods unless they are provided in source (like default constructors). The '==' operator could also be implemented as javac generated method. I think it would be nice if .equals()/.hashCode() were user-definable for value types, yes. As with value-like classes, sometimes the author would not want all components to participate in equality tests, or would like to change the way some component is compared - in particular when components can also be pointers to objects (i.e. reference type components). Regards, Peter > >> I think default .equals() method for value types should be the bit-wise >> compare of all fields. I think this is a very important canonical equals >> and hard to implement in custom method easily (because of peculiarities >> of float and double). Like default equals for reference types, it is an >> equivalence relation with the greatest possible number of equivalence >> classes. The default .hashCode() method could then be some quick >> bit-wise sum of public fields. If there are no public fields, it would >> simply be 0. Value types holding sensitive information would then have >> to contain some public uniquifying field if they wanted to be used as >> keys in hash maps or implement a secure hash algorithm if they hold >> enough entropy. >> >> Regards, Peter From twhitmore.nz at gmail.com Fri Dec 26 01:28:49 2014 From: twhitmore.nz at gmail.com (Thomas W) Date: Fri, 26 Dec 2014 14:28:49 +1300 Subject: valhalla-dev Digest, Vol 6, Issue 3 In-Reply-To: <5496F99D.3060107@oracle.com> References: <5496F99D.3060107@oracle.com> Message-ID: Hi Brian, people, Thanks for your thoughts! A few responses, some questions and a couple of other points: 1) Re: List.remove() disambiguation ----------------------------------------------------------- Your solution here amounts to a deprecation mechanism with hints, which is > an OK solution to the remove(int)/remove(Object) problem. > Yes, but having thought further, it would probably be clearest to definitively rename the methods & annotate the "legacy compatibility" name to generate a bridge method. @LegacyName(whenUnambiguous="remove") public T removeAt (int index); 2) Type signature of removeAll(Collection), remove(Object item) ----------------------------------------------------------- ------------------------------------- I made a start on addressing this in my previous post; in regards to the type of remove() 'item' parameter. At that stage I called the concept "compatible" -- which is perhaps too strong, as the specific & exact intent is "any subtype or ancestor of T" -- essentially, any inheritance relative that could _potentially_ be compatible. Now my understanding -- which may or may not be exactly correct -- is that remove() and removeAll() signatures were typed wider, to allow for clients (with less knowledge of specific type) to remove elements from collections created with a more-specific type. So the possibility I proposed, was to express this as a type expression. For reference types, it would resolve as before; for value types, absent any notion of inheritance, it would just flatten to the value type. public boolean removeItem (CT item); public boolean removeAll (Collection items); Of course, syntax is just invented here :) 3) General thoughts & new proposal on Method-Level vs Layers -------------------------------------------------------------------------------------------- Essentially there are two ways to solve the kind of problems we're discussing. 1) annotations & type-expression syntaxes, at the method level 2) groups of the above, as a "Layer". I'm now going to propose a third alternative, for consideration: 3) method level, using shared type-expressions visible only within the class. public interface ListLike { protected type CT compatible T; // type-expression shared across methods, but not public public boolean removeItem (CT item); public boolean removeAll (Collection items); } This third alternative achieves "sharing" similar to Layers/Peeling of type expressions, while keeping method declarations & annotations independent. We would gain some of the benefits of layering, but only introduce a new member type -- which can be ignored for almost all other purposes -- rather than a major structural level. 4) Combinatorial & Utility-class drawbacks to Layering ------------------------------------------------------------------------------- Layers/Peeling have been proposed as an approach, initially for classes genericized on one type-parameter. I'm not super mathematical/ or an expert on this, but I wonder if there are some potential problems: 1) Classes parameterized on >1 parameter, are going to suffer a combinatorial explosion of layer signatures. - whereas the actual requirement to specialize on, is typically going to be one (or occasionally two) of those type-parameters. - layering selectors when we wish to target or will be awkward and ugly. I think it may be the case that method-specific type expressions, may be easier & more efficient to correctly express our requirements for classes genericized on >1 parameter. 2) Utility classes which genericize individual methods/ or groups of methods, rather than being generically typed themselves. - Layering as proposed, applies only within the class-level. - Layering as proposed, also requires a type-parameter to genericize on. - generics in Java are currently perfectly usable at the method level. - should we be ruling out specialization entirely, in all perpetuity, for utility classes/ and individual methods? I know nobody to date has proposed/ or envisaged specializing static methods. We've all been thinking about collections. But should we/ do we actually need to permanently rule this out? It may be "a scope too far" for this iteration, but I think it's an interesting question. 5) Map.get() and "sentinel values" -------------------------------------------------------- You misunderstand. 'Sentinel' or special values have two purposes: 1) for APIs, to return "nothing present"; 2) for internals, to store "nothing present". We are both largely against the second use. But, for a large number of uses Map.get() returning 'null' works great. There is much code already -- Map.get() -- returning a sentinel for "not found". My proposal is to expressly recognize that; and ensure that better values than 0 are used. My initial proposal was to use -1; not perfect I agree, but the bulk of C library APIs has been happy to do without this number for a very long time :) However, I'm happy to revise it to Integer.MIN_VALUE. 'double' could use either MIN_VALUE or NaN. 'boolean' will have false, and that's the best we can do. Since efficiency is the main reason to specialize, we shouldn't require Map.get()'s single-word return to be "blown out" to two; nor should wrapping in Optional be required. Unless we're going to drop Map.get() from the API, which we shouldn't, a sentinel is proveably the only solution. As with Objects, anybody who actually needs to distinguish Integer.MIN_VALUE from "not present" in Map can use the same approaches as present: 1) check containsKey() first, then call get() 2) use getOrDefault() 3) "mask" the sentinel with another value. Usage of the sentinel (for single-return APIs, or -- less recommended -- for internal storage) will be up to the collection author. Given the efficiency of a single machine-word, rather than two, and the absence of multiple-returns or out-parameters from the Java language, this solution is sane, efficient & suitable for performant use. 6) "Syntax digressions" ----------------------------------- My point was to propose _clean and meaningful syntax_ as part of the mechanism -- rather than having us discuss horrible hacks like (cast)null. I'm also suggesting that perhaps, 'null' might become invalid syntax -- having to being explicitly replaced by either of the two meaningful uses for it, 'emptyValue' or 'sentinelValue'. 7) -------------------- Well, it's good that we are introducing some FP functionality into Java. My rant came from deep & long-held feelings and experience. There has been, I guess, an amazing blindness in refusal to address null-handling. Many application developers spend 10% of their lives cleaning up other people's null-handling. I, however, had it sorted. I had beautiful syntax. I had perfect naming. I had it sweet.. Optional.eq() was what i called it :) It's good that we've finally got java.util.Objects, with an Objects.equals() method; soon, we'll no longer need to be 6-compatible and can actually use that class. Here are some constructive suggestions, based on what I actually did: - Objects.text() method returning "" rather than "null", is extremely useful. - eqNoCase() also very useful for business applications. Thanks for your good work on FP.. I know it's not all complete yet. (Optional -> Stream of 0/1 is yet lacking). See: http://stackoverflow.com/questions/22725537/using-java-8s-optional-with-streamflatmap 8) ArrayList & custom specialization --------------------------------------------------------------------- We shouldn't be trying to specialize this down to the 'bit' level -- machine addressing runs at the byte level only. I'm largely against custom specializations -- there's a perfectly good Class mechanism to let more-specific implementations of an interface be provided. For example, you can implement a collection based on BitSet. ------------------------- Thanks Brian & Timo for your feedback, I appreciate everyone's thoughts. Merry Christmas everybody & enjoy the holidays! Regards, Thomas Whitmore From brian.goetz at oracle.com Fri Dec 26 02:02:21 2014 From: brian.goetz at oracle.com (Brian Goetz) Date: Thu, 25 Dec 2014 21:02:21 -0500 Subject: valhalla-dev Digest, Vol 6, Issue 3 In-Reply-To: References: <5496F99D.3060107@oracle.com> Message-ID: <549CC1AD.2080300@oracle.com> > Yes, but having thought further, it would probably be clearest to > definitively rename the methods & annotate the "legacy compatibility" > name to generate a bridge method. Yes, this is the option we refer to as "nuke them from orbit". We could do this -- and have of course considered it -- but we hope to do better. > At that stage I called the concept "compatible" -- which is perhaps too > strong, as the specific & exact intent is "any subtype or ancestor of T" > -- essentially, any inheritance relative that could _potentially_ be > compatible. > > Now my understanding -- which may or may not be exactly correct -- is > that remove() and removeAll() signatures were typed wider, to allow for > clients (with less knowledge of specific type) to remove elements from > collections created with a more-specific type. > > So the possibility I proposed, was to express this as a type expression. > For reference types, it would resolve as before; for value types, > absent any notion of inheritance, it would just flatten to the value type. > > public boolean removeItem (CT item); > public boolean removeAll (Collection items); > > Of course, syntax is just invented here :) This is similar to what we're calling "loose override", where a signature that is "typed wider" but erasure-equivalent could be considered an override when restricted to erased-reference receivers. Then the signature of removeAll could really be removeAll(Collection), and the legacy erased-ref signature could be considered an implementation of that modulo erasure. > 4) Combinatorial & Utility-class drawbacks to Layering All of these are indeed relevant concerns (some of which we have reasonable sketches on the whiteboard for), but I think you're still a bit obsessed with reducing the syntactic footprint. At this point, the important part is finding the right *model* for things like inheritance and membership; when we find the right model, hopefully the syntax works itself out. > There is much code already -- Map.get() -- returning a sentinel for "not > found". My proposal is to expressly recognize that; and ensure that > better values than 0 are used. > > My initial proposal was to use -1; not perfect I agree, but the bulk of > C library APIs has been happy to do without this number for a very long > time :) However, I'm happy to revise it to Integer.MIN_VALUE. 'double' > could use either MIN_VALUE or NaN. 'boolean' will have false, and that's > the best we can do. I think you're being a little too quick to accept not-perfect for an answer! I actually think this route is unacceptable -- its just too error-prone. The ship sailed on using the full range of primitives values years ago. > Since efficiency is the main reason to specialize, we shouldn't require > Map.get()'s single-word return to be "blown out" to two; nor should > wrapping in Optional be required. > > Unless we're going to drop Map.get() from the API, which we shouldn't, a > sentinel is proveably the only solution. See the new-in-8 getOrDefault() method. This allows clients to pick their own, usage-specific sentinel, without forcing a global and arbitrary choice of sentinels on all primitive users. This, combined with an optional-bearing version for those who can't pick, should cover the waterfront. The "pick an int and make it the sentinel value" approach (and what do we do for the other value types?) is just not good enough. It's even worse that the problems we have with null now, since at least nulls fail fast when you try to use them. WHy would we make this worse? From peter.levart at gmail.com Fri Dec 26 10:45:58 2014 From: peter.levart at gmail.com (Peter Levart) Date: Fri, 26 Dec 2014 11:45:58 +0100 Subject: valhalla-dev Digest, Vol 6, Issue 3 In-Reply-To: References: <5496F99D.3060107@oracle.com> Message-ID: <549D3C66.2060107@gmail.com> Hi Thomas, My thoughts on sentinels, etc... On 12/26/2014 02:28 AM, Thomas W wrote: > There is much code already -- Map.get() -- returning a sentinel for "not > found". My proposal is to expressly recognize that; and ensure that better > values than 0 are used. > > My initial proposal was to use -1; not perfect I agree, but the bulk of C > library APIs has been happy to do without this number for a very long time > :) However, I'm happy to revise it to Integer.MIN_VALUE. 'double' could use > either MIN_VALUE or NaN. 'boolean' will have false, and that's the best we > can do. > > Since efficiency is the main reason to specialize, we shouldn't require > Map.get()'s single-word return to be "blown out" to two; nor should > wrapping in Optional be required. If value types are done right, then "wrapping" a value type inside another value type is not actually wrapping (like we are used to call it with reference types), but embedding. The return of Optional or any Optional does not represent an implementation overhead of another indirection like with reference types. If all goes well, then I think the plan is for "blowing out" a single word int return to double word Optional means the additional word will be assigned to another CPU register in machine code - hardly something we can measure. > Unless we're going to drop Map.get() from the API, which we shouldn't, a > sentinel is proveably the only solution. > > As with Objects, anybody who actually needs to distinguish > Integer.MIN_VALUE from "not present" in Map can use the same > approaches as present: > 1) check containsKey() first, then call get() Not good for ConcurrentMap(s). > 2) use getOrDefault() Unless all the values are needed. > 3) "mask" the sentinel with another value. > > Usage of the sentinel (for single-return APIs, or -- less recommended -- > for internal storage) will be up to the collection author. I think that the desire to use a sentinel for internal storage in value-type based data structures such as collections is greater than just for returns from get() or such which are not problematic at all if Optional is used instead. Take for example a HashMap. What would be the most efficient representation of specialized HashMap for example? Perhaps a linear-scan hash table implemented as Map.Entry[] array. So what is the most efficient representation of specialized Map.Entry ? Here, using a sentinel value for "not-present" key can save 1/3 or even 1/2 (depends on alignment constraints on various architectures) of memory used for such a structure. With larger value types as keys and/or values, additional flag in Map.Entry implementation does not matter much any more. So we might need two implementations - with and without sentinel keys. > Given the efficiency of a single machine-word, rather than two, and the > absence of multiple-returns or out-parameters from the Java language, this > solution is sane, efficient & suitable for performant use. But value types as return types "are" in effect multiple-returns, packaged in a disguise of a class-like thing. Regards, Peter From twhitmore.nz at gmail.com Mon Dec 29 01:40:55 2014 From: twhitmore.nz at gmail.com (Thomas W) Date: Mon, 29 Dec 2014 14:40:55 +1300 Subject: Wider Structural Considerations, versus Sentinels Message-ID: Hi Peter, Brian, people, I'm warming to 'Layering' as an approach -- it avoids many issues with nulls and method-naming -- but don't yet feel specialization itself, can justify the structural & language footprint needed for layering. The simpler alternative I proposed uses syntactical constructs, at the method level, with the goal of having a single "specializable" class flatten appropriately to both reftype & valuetype implementations (eg, Map and Map). Until we can make a strong determination, I would like to continue entertaining both possible approaches. We can compare them thus: A) Layering: - "layers" selected by subtype, - to provide extra methods/bridges, - and API/ implementations suitable for value types (no nulls). B) Method-level approach: - renaming/bridging by annotation, - syntactical constructs to replace direct usages of null; - recommended to include Optional/ or non-sentinel based API also, but that is up to class author. Sentinels ------------ I appreciate the comments on 'Optional' returns and these are obviously desirable to introduce to the API (not in Java 8, though). I believe sentinels _can_ be part of a robust & correct low-level specialization approach, for the following reasons: 1) Map.get() API has already been designed with a single-word return & sentinel-based API. 2) A strong & robust general-purpose specializer should be able to specialize single-word return APIs, no less than others, where such API is desired. 3) API choice is up to the class author. 4) Specialization is about performance; we ought not to force the introduction of wrappers where the explicit purpose is low-level optimization. Sentinel-based APIs may be unsuitable in some circumstances -- I've never proposed them as the only API (!!), just an effective & fairly-equivalent way to transform existing API (Map.get()) to a value-type form. For sentinel-based API to be unsuitable, the first two of the following four conditions have to be met. (That's an AND conjunction). 1) Presence of keys in the map are optional (ie, not fully prepopulated) 2) Full range of 'int' is required for values 3) A 'getOptional()', 'getOrDefault()' or (non-concurrent) containsKey()/get() API not be available 4) A wider (eg. long) value-type cannot be substituted. Just as we see with reftype Map.get(), there are many many usages where a 'sentinel' is not at all a problem. So provided we add a Map.getOptional() API, there are no real problems with still retaining a sentinel-based Map.get(). Essentially, 'null' is a sentinel for reftypes and we have not yet ruled out a simple low-level specializer based on syntactic constructs. Structural Considerations ---------------------------------- Java is a simple language. There are many cases for which we might want, or it would be very convenient to have, a layer of structure between 'class' and 'member'. Some examples: 1) distinct lifecycles; initialization, vs building, vs operational use. 2) separate features: configuration, vs metrics/statistics, vs subordinate components, vs own data, vs active APIs 3) separate interactions: external API, vs component SPI, vs own internal machinery. All of the above (generally, "lifecycles" or "facets") are more than deserving of structure. Do they get it in Java? No. There is no structure in Java other than class, and member. Another two cases, less deserving: 4) Properties -- famously weakly-structured in Java 5) mixins or multiple inheritance For a long time I have been amazed by properties & Javadoc. Why would anyone sort or document a behaviour-free getter/setter combination separately??? But that is how the Java language is specified. We've learned to live without structure, and Java functions well enough as a class- and member-based language. If we're going to add structure, it should address more than such a tiny corner case! Wider Consideration of "Structure" --------------------------------------------- Essentially my point is, that if we're going to look at adding structure, it maybe that we should add it more widely -- not just for specialization. Many other aspects of classes could benefit from better structure, and the overhead to add a large feature to Java language for just a small number of method & null fixups doesn't justify it. Could this be a possible example? class OrderBuilder { lifecycle Configuration { @Autowired public void setOrderService (OrderService orderService); @Autowired public void setWarehouseService (WarehouseService warehouseService); } lifecycle Building > Configuration implements IOrderReceiver { public void addItem (OrderItem item); } lifecycle Operation > Building { public Order result(); } } I'd like to explore the area of "structure", to see what useful things we can do with it. If we _can_ justify the cost by achieving other benefits, I am all for going Layering. Of course, failing that I'm still a Grinch :) What are people's thoughts on feature/ lifecycle/ interaction structuring? How can they be used? Even organizing Javadocs & source to not be such a jumble-sale of methods, could be a major improvement. What else can we do with a moderately-simple structural mechanism? Comments? Regards, Thomas From gavin at hibernate.org Wed Dec 31 20:27:36 2014 From: gavin at hibernate.org (Gavin King) Date: Wed, 31 Dec 2014 21:27:36 +0100 Subject: Fwd: Proposal for generics over primitives needs a rethink In-Reply-To: References: Message-ID: Hi, I read with interest the document here: http://cr.openjdk.java.net/~briangoetz/valhalla/specialization.html I'm rather concerned with this proposal, which introduces additional irregularities and complications into the type system of Java, instead of attacking the underlying cause of the irregularity, which is that there is no root type abstracting over primitives and reference types. In my opinion, this proposal should not be implemented as written, since it adds additional complexity to an area of the language (variance/wildcards) which is already too complex, and is already an area which many professional Java developers don't completely understand. The proposal as it exists today runs a serious risk of making Java worse. What this proposal does is introduce parametric polymorphism over primitive types, while leaving it impossible to abstract over primitives and reference types with subtype polymorphism. Thus, at the intersection of the two systems of abstraction, namely, *variance*, we get the broken behavior that a List isn't a List. The proposal also ties itself in knots trying to explain which operations are and are not sound for a type variable of form "any T", as a list of special casey restrictions, all the while pretending that these restrictions can't possibly be represented within the type system itself. Finally, worst of all, the proposal fails to separate a description of the type system being proposed from a bunch of details about how that type system could hypothetically be implemented in today's JVM. I therefore suggest a different, simpler, and much more natural starting point for this work: stop pretending that there is no type Any. If we accept that there is a type Any, from which Object, int, float, and friends all descend, then: - it's clear at the declaration site what is the difference between "interface X" and "interface X", and it is crystal clear what are the operations that are legal for a T in either case, and - it's clear at the use site what is the difference between the instantiations List and List, and we obtain the correct subtyping relationships that List and List are both subtypes of List. Furthermore, the notion of parametric abstraction over primitive types falls out naturally without the need to introduce new primitive constructs and syntax ("any T") into the language. Then, finally, working from this simpler, more elegant, more correct model, we can ask ourselves how it's possible to implement this type system (either at the compiler level, or, much preferably via enhancements to the VM itself). This is instead of starting from a convenient implementation and then working backwards to obtain a broken type system, which seems to be what has happened with the current proposal. I readily expect objections that this might break existing code. I therefore humbly request that such objection should come with example code written in Java 8 which would be broken by the introduction of an Any type. I can't think of any, but surely I could be missing something. (I am aware of one case which might require some finessing, but I can think of at least two solutions which would likely work.) Thanks, Gavin -- Gavin King gavin.king at gmail.com http://in.relation.to/Bloggers/Gavin http://hibernate.org http://seamframework.org From brian.goetz at oracle.com Wed Dec 31 22:33:02 2014 From: brian.goetz at oracle.com (Brian Goetz) Date: Wed, 31 Dec 2014 17:33:02 -0500 Subject: Proposal for generics over primitives needs a rethink Message-ID: <54A4799E.3050300@oracle.com> Thanks, Gavin, for bringing up this point. I'm actually a little surprised that no one has asked this question before; after all, the "why not 'just' have an Any type" question is kind of an obvious one after you start thinking about this problem for a few minutes. *Obviously* it would be more desirable to integrate primitives and values into generics by leaning on the existing notion of type bound, rather than introducing all the additional complexity that we're considering. (Also obviously, this must have occurred to us in the first five minutes of thought. So why, after so much effort, have we said nothing about this possible approach? Indeed, it's on our (long) to-do list to write up some of our analysis of various roads not taken, including this one.) When designing a language (at least, one intended for real work), you need to pay attention to both the part where it meets the user, *and* the part where it meets the compilation target; if the mapping between source-level concepts and target-level concepts is not sufficiently straightforward, bad things will happen. But, most suggestions we receive for evolving Java tend to focus only on the former. (This is natural; developers usually only see the source code, not the bytecode, and even some language designers are willing to accept dramatic impedance mismatches between source code and bytecode if it gets them to their expressiveness goals.) But the reality is that, if we were to ignore the latter, people would be happy for a few minutes and then unhappy forever due to the parade of corner cases, complexity, and performance potholes that this approach generally leads to. We don't want to do this to our users. (We are lucky enough to have some control over our compilation target, but we're also constrained there as well by the same compatibility requirements.) For the record, the reason we rejected a unified 'Any' type is: it is a fiction. (A "unifiction". (https://twitter.com/BrianGoetz/status/461539994197585920)). Sure, it's easy to use 'Any' as a pseudo-type bound, and we could certainly choose to denote "Foo" as "Foo", but all this does is draw the user further into the Any fiction while not actually making it a reality. Where the wheels start to come off the wagon is: how do we represent a variable of type 'Any" in bytecode (a field, local variable, or method parameter or return type)? If we can't answer that, we can't allow use of Any in these places. And solving this problem amounts to only slightly less than a total redesign of the JVM and bytecode architecture. So this harmless-seeming question (couched in claims of "simpler" and "more elegant") amount to "Why not just redesign the VM completely." Languages that have attempted to unify primitives and references on the JVM, with the existing bytecode architecture, while retaining some sort of compatibility with existing Java idioms, have failed at doing so. (And I am thankful to have those experiments to inform our work here!) As a concrete example, I point you to Paul Philips' excellent "Scala War Stories" talk from JVM Language Summit 2013, which covers the failure of such unifictions, and more: http://medianetwork.oracle.com/video/player/2623635250001 But you might say "Wait a second, C# managed to pull off this redesign of the VM to support polymorphism over objects and primitives". And indeed they did, and overall their solution is quite elegant. And obviously, we must have known about this example, so why wouldn't we explore this? Well, obviously we have. The cost of the C# approach is that existing classes could not be gradually migrated to be generic; existing collections had to be effectively deprecated and replaced, or a "flag day" had to be declared where all the code (library and client) changes simultaneously. These are not options for us. At the risk of being obnoxious, C# was able to get away with it because at the time, they had a very small base of existing users and code and were not yet successful enough to have to worry about compatibility. Lucky for them, unlucky for us. Some more comments inline. > I'm rather concerned with this proposal We're concerned with it too, as I think we've made quite clear. Here's the position we're in: if we wait until we have a complete, 100% solution before sharing anything, people throw rocks at us for doing everything behind closed doors, but if we share our working thoughts in progress, people throw rocks at us for being half-baked. We've chosen the latter poison, so by all means, throw your rocks, but don't kid yourself that you've spotted something that no one else has. (And please, check the attitude at the door, it's just not helpful.) > What this proposal does is introduce parametric polymorphism over > primitive types, while leaving it impossible to abstract over > primitives and reference types with subtype polymorphism. Thus, at the > intersection of the two systems of abstraction, namely, *variance*, we > get the broken behavior that a List isn't a List. Indeed, we've already pointed this out, and its not pretty. All constructive suggestions accepted. But implicitly dropping a key requirement (like gradual migration compatibility), and then claiming there's an obvious answer, is not really helpful. > I therefore suggest a different, simpler, and much more natural > starting point for this work: stop pretending that there is no type > Any. This is a particularly funny way to put it, as it is the notion that there *is* an Any type which requires pretending! There is simply no way (without boxing) to represent this on the JVM as it currently stands. But if boxing were good enough, then we wouldn't need to do anything -- we'd just write ArrayList and be done with it! But obviously boxing isn't good enough, since we're having this conversation. Which means you need a VM story for how we're going to represent a flattened array of XY-points or make ArrayList actually be backed by an int[] array or inline value types into containing classes, and still plays nicely with generics. Where the data hits the heap is where the boxing story (and therefore the Any story) falls apart. All in all, you paint a picture of a beautiful world, but not the one we find ourselves living in. If we were designing a language from scratch, or didn't have users, or hated our users, we would certainly be exploring this approach in preference to the current approach we've staked out. (This is so obvious I wish I didn't even have to say it.) But we're not ready to throw our users under the bus to the degree that this approach seems to entail. But if we've missed something obvious, by all means, point it out (but please, constructively). And, feel free to prove us wrong! Try implementing the changes you are envisioning in the JVM, and show how they can get us to the goal! From forax at univ-mlv.fr Wed Dec 31 22:58:25 2014 From: forax at univ-mlv.fr (Remi Forax) Date: Wed, 31 Dec 2014 23:58:25 +0100 Subject: Proposal for generics over primitives needs a rethink In-Reply-To: <54A4799E.3050300@oracle.com> References: <54A4799E.3050300@oracle.com> Message-ID: <54A47F91.4040701@univ-mlv.fr> Just to add that there is another cost with the C# approach, you must have exactly the same bytecode for Set and Set so you can not by example, specialize Set to use a bitset. About the introduction of a type Any in the VM, it means that now we have a type that can store a primitive or a reference, we know how to represent this kind of type using tag bits (like V8 does) or Nan boxing (like Mozilla"s *Monkey VM does). Basically, representing Any in the VM is like asking for transform a Java VM into something very close to a Javascript VM. happy new year, R?mi On 12/31/2014 11:33 PM, Brian Goetz wrote: > Thanks, Gavin, for bringing up this point. > > I'm actually a little surprised that no one has asked this question > before; after all, the "why not 'just' have an Any type" question is > kind of an obvious one after you start thinking about this problem for > a few minutes. > > *Obviously* it would be more desirable to integrate primitives and > values into generics by leaning on the existing notion of type bound, > rather than introducing all the additional complexity that we're > considering. (Also obviously, this must have occurred to us in the > first five minutes of thought. So why, after so much effort, have we > said nothing about this possible approach? Indeed, it's on our (long) > to-do list to write up some of our analysis of various roads not > taken, including this one.) > > When designing a language (at least, one intended for real work), you > need to pay attention to both the part where it meets the user, *and* > the part where it meets the compilation target; if the mapping between > source-level concepts and target-level concepts is not sufficiently > straightforward, bad things will happen. But, most suggestions we > receive for evolving Java tend to focus only on the former. (This is > natural; developers usually only see the source code, not the > bytecode, and even some language designers are willing to accept > dramatic impedance mismatches between source code and bytecode if it > gets them to their expressiveness goals.) > > But the reality is that, if we were to ignore the latter, people would > be happy for a few minutes and then unhappy forever due to the parade > of corner cases, complexity, and performance potholes that this > approach generally leads to. We don't want to do this to our users. > (We are lucky enough to have some control over our compilation target, > but we're also constrained there as well by the same compatibility > requirements.) > > For the record, the reason we rejected a unified 'Any' type is: it is > a fiction. (A "unifiction". > (https://twitter.com/BrianGoetz/status/461539994197585920)). Sure, > it's easy to use 'Any' as a pseudo-type bound, and we could certainly > choose to denote "Foo" as "Foo", but all this > does is draw the user further into the Any fiction while not actually > making it a reality. > > Where the wheels start to come off the wagon is: how do we represent a > variable of type 'Any" in bytecode (a field, local variable, or method > parameter or return type)? If we can't answer that, we can't allow > use of Any in these places. And solving this problem amounts to only > slightly less than a total redesign of the JVM and bytecode > architecture. So this harmless-seeming question (couched in claims of > "simpler" and "more elegant") amount to "Why not just redesign the VM > completely." > > Languages that have attempted to unify primitives and references on > the JVM, with the existing bytecode architecture, while retaining some > sort of compatibility with existing Java idioms, have failed at doing > so. (And I am thankful to have those experiments to inform our work > here!) As a concrete example, I point you to Paul Philips' excellent > "Scala War Stories" talk from JVM Language Summit 2013, which covers > the failure of such unifictions, and more: > http://medianetwork.oracle.com/video/player/2623635250001 > > But you might say "Wait a second, C# managed to pull off this redesign > of the VM to support polymorphism over objects and primitives". And > indeed they did, and overall their solution is quite elegant. And > obviously, we must have known about this example, so why wouldn't we > explore this? > > Well, obviously we have. The cost of the C# approach is that existing > classes could not be gradually migrated to be generic; existing > collections had to be effectively deprecated and replaced, or a "flag > day" had to be declared where all the code (library and client) > changes simultaneously. These are not options for us. At the risk of > being obnoxious, C# was able to get away with it because at the time, > they had a very small base of existing users and code and were not yet > successful enough to have to worry about compatibility. Lucky for > them, unlucky for us. > > Some more comments inline. > >> I'm rather concerned with this proposal > > We're concerned with it too, as I think we've made quite clear. Here's > the position we're in: if we wait until we have a complete, 100% > solution before sharing anything, people throw rocks at us for doing > everything behind closed doors, but if we share our working thoughts > in progress, people throw rocks at us for being half-baked. We've > chosen the latter poison, so by all means, throw your rocks, but don't > kid yourself that you've spotted something that no one else has. (And > please, check the attitude at the door, it's just not helpful.) > >> What this proposal does is introduce parametric polymorphism over >> primitive types, while leaving it impossible to abstract over >> primitives and reference types with subtype polymorphism. Thus, at the >> intersection of the two systems of abstraction, namely, *variance*, we >> get the broken behavior that a List isn't a List. > > Indeed, we've already pointed this out, and its not pretty. All > constructive suggestions accepted. But implicitly dropping a key > requirement (like gradual migration compatibility), and then claiming > there's an obvious answer, is not really helpful. > >> I therefore suggest a different, simpler, and much more natural >> starting point for this work: stop pretending that there is no type >> Any. > > This is a particularly funny way to put it, as it is the notion that > there *is* an Any type which requires pretending! There is simply no > way (without boxing) to represent this on the JVM as it currently > stands. But if boxing were good enough, then we wouldn't need to do > anything -- we'd just write ArrayList and be done with it! > But obviously boxing isn't good enough, since we're having this > conversation. Which means you need a VM story for how we're going to > represent a flattened array of XY-points or make ArrayList > actually be backed by an int[] array or inline value types into > containing classes, and still plays nicely with generics. Where the > data hits the heap is where the boxing story (and therefore the Any > story) falls apart. > > All in all, you paint a picture of a beautiful world, but not the one we > find ourselves living in. If we were designing a language from scratch, > or didn't have users, or hated our users, we would certainly be > exploring this approach in preference to the current approach we've > staked out. (This is so obvious I wish I didn't even have to say it.) > But we're not ready to throw our users under the bus to the degree > that this approach seems to entail. But if we've missed something > obvious, by all means, point it out (but please, constructively). > > And, feel free to prove us wrong! Try implementing the changes you > are envisioning in the JVM, and show how they can get us to the goal! > >