From brian.goetz at oracle.com Tue Dec 6 19:37:04 2016 From: brian.goetz at oracle.com (Brian Goetz) Date: Tue, 6 Dec 2016 14:37:04 -0500 Subject: Update on JEP-286 (Local Variable Type Inference) Message-ID: <07927e73-0473-3a20-5646-1f2d698d2f86@oracle.com> [ Please do not respond directly; see below for instructions on providing feedback. ] Over 2500 people participated in two rounds of surveys on Local Variable Type Inference (http://openjdk.java.net/jeps/286). The results of the first round can be found at: https://www.surveymonkey.com/results/SM-FLWGS5PW/ The results of the followup survey are here: https://www.surveymonkey.com/results/SM-Q63DFRZW/ Responses to many of the issues raised in the survey are here: http://mail.openjdk.java.net/pipermail/platform-jep-discuss/2016-March/000039.html http://mail.openjdk.java.net/pipermail/platform-jep-discuss/2016-March/000063.html Some analysis on readability, and goals, can be found here: http://mail.openjdk.java.net/pipermail/platform-jep-discuss/2016-March/000064.html Some of these have been collected into a FAQ, here: http://cr.openjdk.java.net/~briangoetz/jep-286/lvti-faq.html We'll be pushing an implementation soon that people can try out. SUMMARY OF THE SURVEY RESULTS ----------------------------- Overall, the responses were strongly in favor of the feature; 74% were strongly in favor, with another 12% mildly in favor. 10% thought it was a bad idea. The written comments had more of a negative bias, but this shouldn't be surprising; people generally have more to say in disagreement than in agreement. The positive comments were very positive; the negative comments were very negative. So no matter what we do here, some people are going to be very disappointed. When given a choice, the most popular syntax choice was "val and var", with "var only" as the second choice (the others were all obvious losers). But when asked about how people felt about these choices, we saw a divergence; more people liked var/val, but more people hated it too. While there were some passionate arguments against, the numbers speak loudly: this is a feature that most developers want. (It is the most frequently repeated request of developers coming to Java from other languages.) READABILITY ----------- The biggest category of negative comments regarded worries about readability (though most of these came from folks who have never used the feature; those who have used it in other languages were overwhelmingly positive). We have always held out "Reading code is more important than writing code" as a core value of the language; plenty of folks took the opportunity to throw this seeming inconsistency in our face, on the assumption that this feature would inevitably lead to less readable code. For example, code like the following strawman was offered by several commenters: var x = y.getFoo() as evidence of "see, its unreadable, you have no idea what 'x' is." The readability problem here, though, stems from the fact that 'x' is just a poorly chosen variable name. Having a manifest type might make up for the programmer's laziness, but it would be better to just choose a good variable name in the first place. While every situation may be different, we believe that, with judicious use of this feature in well-written code, readability is actually *enhanced*. Consider a block of locals: UserModelHandle userDB = broker.findUserDB(); List users = db.getUsers(); Map addressesByUser = db.getAddresses(); What is the most important thing on each line, the variable *name*, the variable *type*, or the initializing expression? We claim it is the name that is most important -- because they describe the role of the variable *in the current program*. And the variables names are not so easy to visually pick out from the above code -- they're stuck in the middle of each line, and at a different place on each line. Ideally, we'd like for the most important thing to be front-and-center in the reader's view. If we rewrite the above block with inferred types: var userDB = broker.findUserDB(); var users = db.getUsers(); var addressesByUser = db.getAddresses(); the true intent of this code pops out much more readily; the variable names are (almost) front and center. The lack of manifest types is not an impediment, because we've chosen good variable names. Another aspect in which this feature could improve readability is that users frequently construct complex nested and chained expressions, not because this is the most readable way to write the code, but because the overhead of declaring additional temporary variable seems burdensome. (We all do this.) By reducing this overhead, implementation patterns will likely reequilibrate to a less artificially-condensed form, enhancing readability. MUTABILITY ---------- Many of the comments were not so much about the use of type inference, but about mutability -- a lot of people like the idea of reducing the ceremony associated with finality. (And we like this idea too.) Initially, we considered that perhaps inference would only apply to effectively final locals. But after working with a prototype, we saw that this had an undesirable side-effect; mutable locals stick out badly: var immutableLocal = ... var anotherImmutableLocal = ... var alsoImmutable = ... LocalDateTime latestDateSeenSoFar = ... var thisOneDoesntChangeEither = ... Fans of immutability might enjoy that mutability is punished in this way, but the irregularity was definitely annoying to those who tried this version. Both of the paired versions (var/val, var/let) suffered from a similar problem. Some readers found that var/val were so similar that they could mostly ignore the difference: var immutableLocal = ... var anotherImmutableLocal = ... var alsoImmutable = ... val latestDateSeenSoFar = ... var thisOneDoesntChangeEither = ... whereas others found the small difference distracted them from the more important parts of the code. Similarly, some found the var/let distinction distracting, whereas others liked it: var immutableLocal = ... var anotherImmutableLocal = ... var alsoImmutable = ... let latestDateSeenSoFar = ... var thisOneDoesntChangeEither = ... Immutability is important, but in reality, local variables are the least important place where we need more help making things immutable. Local variables are immune to data races; most locals are effectively final anyway. Where we need more help in encouraging immutability is *fields* -- but applying type inference there would be foolish. Further, the var/val distinction makes far more sense in other languages than in Java. In Scala, for example, all variables -- locals and fields alike -- are declared with "val name : type", where you can omit the ": type" if you want inference. So not only is mutability orthogonal to inference, but the power of the var/val distinction is greater because it is used in multiple contexts -- but we'd only use it for local variables, and only when their types are inferred. (While the "name : type" syntax may be superior for this reason (and also because it moves the more important component forward), this ship sailed twenty years ago.) So var/val is a feature that *looks* like it carries over cleanly, but in reality suffers greatly in translation. SYNTAX ------ I know this is the part people really care about :) After considering the pros and cons at length, there appears to be an obvious winner -- var-only. Reasons for this include: - While it was not the most popular choice in the survey, it was clearly the choice that the most people were OK with. Many hated var/val; others hated var/let. Almost no one hated var-only. - Experience with C# -- which has var only -- has shown that this is a reasonable solution in Java-like languages. There is no groundswell of demand for "val" in C#. - The desire to reduce the ceremony of immutability is certainly well-taken, but in this case is pushing on the wrong end of the lever. Where we need help for immutability is with fields, not with locals. But var/val doesn't apply to fields, and it almost certainly never will. - If the incremental overhead of getting mutability control over that of type inference were zero, there might be a stronger case, but it was clear that many people found two different leading keywords to be a distraction that kept their eyes from quickly settling on the important stuff. If variable names are more important than types, they're more important than mutability modifiers too. PROVIDING FEEDBACK ------------------ To keep the signal-to-noise ratio to an acceptable level, we're asking people to provide (constructive) feedback through the following survey, whose results will be made public. https://www.surveymonkey.com/r/FBT9WYP Thanks for all your feedback so far! From mark.reinhold at oracle.com Tue Dec 6 23:48:00 2016 From: mark.reinhold at oracle.com (mark.reinhold at oracle.com) Date: Tue, 6 Dec 2016 15:48:00 -0800 (PST) Subject: JEP 300: Augment Use-Site Variance with Declaration-Site Defaults Message-ID: <20161206234800.4B25021102@eggemoggin.niobe.net> New JEP Candidate: http://openjdk.java.net/jeps/300 - Mark From mark.reinhold at oracle.com Tue Dec 6 23:49:01 2016 From: mark.reinhold at oracle.com (mark.reinhold at oracle.com) Date: Tue, 6 Dec 2016 15:49:01 -0800 (PST) Subject: JEP 301: Enhanced Enums Message-ID: <20161206234901.64F5221105@eggemoggin.niobe.net> New JEP Candidate: http://openjdk.java.net/jeps/301 - Mark From mark.reinhold at oracle.com Tue Dec 6 23:50:02 2016 From: mark.reinhold at oracle.com (mark.reinhold at oracle.com) Date: Tue, 6 Dec 2016 15:50:02 -0800 (PST) Subject: JEP 302: Lambda Leftovers Message-ID: <20161206235002.71F1221109@eggemoggin.niobe.net> New JEP Candidate: http://openjdk.java.net/jeps/302 - Mark From forax at univ-mlv.fr Wed Dec 7 08:37:45 2016 From: forax at univ-mlv.fr (Remi Forax) Date: Wed, 7 Dec 2016 09:37:45 +0100 (CET) Subject: JEP 302: Lambda Leftovers In-Reply-To: <20161206235002.71F1221109@eggemoggin.niobe.net> References: <20161206235002.71F1221109@eggemoggin.niobe.net> Message-ID: <1328186127.992463.1481099865770.JavaMail.zimbra@u-pem.fr> I really appreciate this proposal, i hit both better disambiguation and shadow of lambda parameters issues quite frequently. For treatment of underscores, as i understand, the idea is that you can use '_' as parameter without having '_' being entered in the scope of the method, i.e. this code will not compile: void setBar(Bar _) { foo(_); } cheers, R?mi ----- Mail original ----- > De: "mark reinhold" > ?: "maurizio cimadamore" > Cc: platform-jep-discuss at openjdk.java.net > Envoy?: Mercredi 7 D?cembre 2016 00:50:02 > Objet: JEP 302: Lambda Leftovers > New JEP Candidate: http://openjdk.java.net/jeps/302 > > - Mark From forax at univ-mlv.fr Wed Dec 7 09:03:36 2016 From: forax at univ-mlv.fr (Remi Forax) Date: Wed, 7 Dec 2016 10:03:36 +0100 (CET) Subject: JEP 301: Enhanced Enums In-Reply-To: <20161206234901.64F5221105@eggemoggin.niobe.net> References: <20161206234901.64F5221105@eggemoggin.niobe.net> Message-ID: <2000462996.1011073.1481101416087.JavaMail.zimbra@u-pem.fr> I don't really like this proposal, it tries to resolve a corner case but breaks an important feature of the enum, the type of the values of an enum is the same as the enum. Enums are a convenience feature, not something that should be used to design a hierarchy of types because, the hierarchy is closed and designing a hierarchy with an abstract base class is so 2000 . We now have lambdas, so there is no reason to use 'abstract' enums anymore. Instead of interface Activity { void perform(); } enum Activities implements Activity { FOO { public void perform() { /* FOO */ } }, BAR { public void perform() { /* BAR */ } } } it's better to write: interface Activity { void perform(); } enum Activities implements Activity { FOO(() -> { /* FOO */ }), BAR(() -> { /* BAR */ }); private final Runnable runnable; private Activities(Runnable runnable) { this.runnable = runnable; } public void perform() { runnable.run(); } } Here, you have only one class at compile time, the lambdas are created at runtime and the way the hierarchy is implemented is hidden from the public API. I think the GoF name this design pattern as the external decorator or something like this and it's 'use delegation instead of inheritance' to its full glory. Now, If this proposal is accepted, at least, instead of changing the spec to introduce sharp types for all kind of enums, adding sharp type only for generics enums, it will break no code because generics enum currently do not compile. regards, R?mi ----- Mail original ----- > De: "mark reinhold" > ?: "maurizio cimadamore" > Cc: platform-jep-discuss at openjdk.java.net > Envoy?: Mercredi 7 D?cembre 2016 00:49:01 > Objet: JEP 301: Enhanced Enums > New JEP Candidate: http://openjdk.java.net/jeps/301 > > - Mark From martijnverburg at gmail.com Wed Dec 7 09:10:00 2016 From: martijnverburg at gmail.com (Martijn Verburg) Date: Wed, 7 Dec 2016 09:10:00 +0000 Subject: JEP 302: Lambda Leftovers In-Reply-To: <1328186127.992463.1481099865770.JavaMail.zimbra@u-pem.fr> References: <20161206235002.71F1221109@eggemoggin.niobe.net> <1328186127.992463.1481099865770.JavaMail.zimbra@u-pem.fr> Message-ID: I'll preface this with IANALE (I Am Not A Language Expert), TLDR: I've seen direct evidence of not being able to shadow lambda parameters actually being beneficial for readability. ----- I currently read a lot of code by developers who are using lambdas and wanted to add some anecdotal evidence to the shadowing use case. I notice the JEP author has already stated: "It would be desirable to lift this restriction, and allow lambda parameters (and locals declared with a lambda) to shadow variables defined in enclosing scopes. (One possible argument against is readability: if lambda parameters are allowed to shadow, then in the above example, the identifier 'key' means two different things in the two places where it is used, and there seem to be no syntactic barrier to separate the two usages.)" --- The readability issue is really cropping up a lot with the lambdas code I'm seeing. Many developers are already following a short hand idiom for lambda variables e.g. using 'k' instead of 'key', along with some other idioms that do lessen the readability of lambdas based code in general. This is clearly not the fault of the language / syntax today, it's more the fault of the developer! A similar argument can be applied to the proposed 'var' JEP, as long a developers name their variables properly, readability is maintained. That said, the current status quo of not being able to shadow lambda parameters is actually forcing developers to think more clearly about naming and scope, which is generally a good thing. My concern is that if we are able to shadow lambda parameters this will cause even more confusion to the reader unless they carefully hover over the section in their favourite IDE *or* have the 'scope of variables outside of the lambda vs inside the lambda' concept firmly in their heads (an educational issue). ---- As a side note, JEPs 300, 301 and 302 are very cool. Anything that improves type inference and safety automatically for the developer is a welcome addition and I appreciate how hard it is to get that right internally in the JVM and in the language. Cheers, Martijn On 7 December 2016 at 08:37, Remi Forax wrote: > I really appreciate this proposal, > i hit both better disambiguation and shadow of lambda parameters issues > quite frequently. > > For treatment of underscores, > as i understand, the idea is that you can use '_' as parameter without > having '_' being entered in the scope of the method, > i.e. this code will not compile: > > void setBar(Bar _) { > foo(_); > } > > cheers, > R?mi > > ----- Mail original ----- > > De: "mark reinhold" > > ?: "maurizio cimadamore" > > Cc: platform-jep-discuss at openjdk.java.net > > Envoy?: Mercredi 7 D?cembre 2016 00:50:02 > > Objet: JEP 302: Lambda Leftovers > > > New JEP Candidate: http://openjdk.java.net/jeps/302 > > > > - Mark > From maurizio.cimadamore at oracle.com Wed Dec 7 09:44:27 2016 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Wed, 7 Dec 2016 09:44:27 +0000 Subject: JEP 302: Lambda Leftovers In-Reply-To: <1328186127.992463.1481099865770.JavaMail.zimbra@u-pem.fr> References: <20161206235002.71F1221109@eggemoggin.niobe.net> <1328186127.992463.1481099865770.JavaMail.zimbra@u-pem.fr> Message-ID: <99a5701b-986e-67ed-0b0e-41ecc4585541@oracle.com> On 07/12/16 08:37, Remi Forax wrote: > I really appreciate this proposal, > i hit both better disambiguation and shadow of lambda parameters issues quite frequently. > > For treatment of underscores, > as i understand, the idea is that you can use '_' as parameter without having '_' being entered in the scope of the method, > i.e. this code will not compile: > > void setBar(Bar _) { > foo(_); > } Exactly - '_' is not a variable name - just a placeholder you can use in a variable declaration in lieu of a variable name. Maurizio > cheers, > R?mi > > ----- Mail original ----- >> De: "mark reinhold" >> ?: "maurizio cimadamore" >> Cc: platform-jep-discuss at openjdk.java.net >> Envoy?: Mercredi 7 D?cembre 2016 00:50:02 >> Objet: JEP 302: Lambda Leftovers >> New JEP Candidate: http://openjdk.java.net/jeps/302 >> >> - Mark From maurizio.cimadamore at oracle.com Wed Dec 7 09:48:44 2016 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Wed, 7 Dec 2016 09:48:44 +0000 Subject: JEP 301: Enhanced Enums In-Reply-To: <2000462996.1011073.1481101416087.JavaMail.zimbra@u-pem.fr> References: <20161206234901.64F5221105@eggemoggin.niobe.net> <2000462996.1011073.1481101416087.JavaMail.zimbra@u-pem.fr> Message-ID: <02520562-42ad-c87a-5ddd-9862159ee054@oracle.com> Thanks for the feedback. I personally run into the lack of sharp typing several times and seen other people stumbling on it too. Do you have some example in mind that will break - other than the ones listed in the JEP? In my mental model, the kind of surprises this introduces are very similar to anonymous inner class types - that is: new Object() { void m() { } }.m(); this is legal code because the receiver expression doesn't have type Object - but has a sharper type (which can 'see' the additional member). This proposal is about doing the same with enums - which accidentally will sit well with adding generics (because in that case, the constants will have a richer generic type than their parent). Maurizio On 07/12/16 09:03, Remi Forax wrote: > Now, If this proposal is accepted, at least, instead of changing the spec to introduce sharp types for all kind of enums, adding sharp type only for generics enums, > it will break no code because generics enum currently do not compile. From nipa at codefx.org Wed Dec 7 10:30:56 2016 From: nipa at codefx.org (Nicolai Parlog) Date: Wed, 7 Dec 2016 11:30:56 +0100 Subject: JEP 302: Lambda Leftovers In-Reply-To: <20161206235002.71F1221109@eggemoggin.niobe.net> References: <20161206235002.71F1221109@eggemoggin.niobe.net> Message-ID: Hi! Great proposal! Especially the underscore is cool, much better than naming those variables "ignored". I wonder whether I should start using two underscores now so I can later replace them with a single one. :) I guess it will be possible to use "_" for multiple parameters? I would like to request a feature regarding method references. I like making non-public methods static to convey the fact that they do not interact with or even change the state of the object they are called on. But this conflicts with the ease of method references: // `isGenderNeutralName` is an instance method names.filter(this::isGenderNeutralName) vs // `isGenderNeutralName` is a static method names.filter(GenderNeutralNameProcessor::isGenderNeutralName) As a consequence I often go back and make it an instance method to keep the reference readable but it hurts because I give up on an immutability signal. It would be awesome if it were possible to reference a static method in the same class without repeating the entire class name. Reusing the `class` keyword seems like an obvious* choice: // `isGenderNeutralName` is a static method names.filter(class::isGenderNeutralName) Using Martijn's shorthand, IANALE (I Am Not A Language Expert) so I have no idea whether this is tractable but it would surely be a nice addition. so long ... Nicolai * I am aware that the obvious idea might be also be a terrible idea. On 07.12.2016 00:50, mark.reinhold at oracle.com wrote: > New JEP Candidate: http://openjdk.java.net/jeps/302 > > - Mark > -- PGP Key: http://keys.gnupg.net/pks/lookup?op=vindex&search=0xCA3BAD2E9CCCD509 Web: http://codefx.org a blog about software development https://www.sitepoint.com/java high-quality Java/JVM content http://do-foss.de Free and Open Source Software for the City of Dortmund Twitter: https://twitter.com/nipafx From maurizio.cimadamore at oracle.com Wed Dec 7 10:36:43 2016 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Wed, 7 Dec 2016 10:36:43 +0000 Subject: JEP 301: Enhanced Enums In-Reply-To: <02520562-42ad-c87a-5ddd-9862159ee054@oracle.com> References: <20161206234901.64F5221105@eggemoggin.niobe.net> <2000462996.1011073.1481101416087.JavaMail.zimbra@u-pem.fr> <02520562-42ad-c87a-5ddd-9862159ee054@oracle.com> Message-ID: For the records - here's a more complete example where lack of sharp typing hurts, I think: http://hg.openjdk.java.net/valhalla/valhalla/langtools/file/ce7460995ffc/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Dynamic.java#l41 The enum defines all possible kinds of constants which can appear as static arguments in an invokedynamic call. As you can see, many of the methods in this enum are 'partial': they only make sense for certain constants, but not for others. Currently, the only way around this, is to declare this method at the root (the enum itself), and then have the method throw some exception if it's not supposed to be implemented for certain constants. I believe this idiom is a red herring; you really don't want the asType/asSymbol be defined for a STRING constant - and if they weren't, you would get more static type checking back which would prevent you from calling methods that are not 'supported' rather than relying to a runtime check. Maurizio On 07/12/16 09:48, Maurizio Cimadamore wrote: > Thanks for the feedback. I personally run into the lack of sharp > typing several times and seen other people stumbling on it too. > > Do you have some example in mind that will break - other than the ones > listed in the JEP? In my mental model, the kind of surprises this > introduces are very similar to anonymous inner class types - that is: > > new Object() { void m() { } }.m(); > > this is legal code because the receiver expression doesn't have type > Object - but has a sharper type (which can 'see' the additional > member). This proposal is about doing the same with enums - which > accidentally will sit well with adding generics (because in that case, > the constants will have a richer generic type than their parent). > > Maurizio > > > On 07/12/16 09:03, Remi Forax wrote: >> Now, If this proposal is accepted, at least, instead of changing the >> spec to introduce sharp types for all kind of enums, adding sharp >> type only for generics enums, >> it will break no code because generics enum currently do not compile. > From maurizio.cimadamore at oracle.com Wed Dec 7 10:47:55 2016 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Wed, 7 Dec 2016 10:47:55 +0000 Subject: JEP 302: Lambda Leftovers In-Reply-To: References: <20161206235002.71F1221109@eggemoggin.niobe.net> <1328186127.992463.1481099865770.JavaMail.zimbra@u-pem.fr> Message-ID: Well taken points Martin. As you mention, we are aware of the readability issue, and I think this is an area where it could be beneficial to gather some data after an initial round of implementation to see where things stand. As a kind of a counter example, consider this: Map mss = ... String s = "hello"; mss.computeIfAbsent(s, s2 -> s2.toLowerCase()); vs. this: mss.computeIfAbsent(s, _ -> s.toLowerCase()); The first is a non-capturing lambda - the second is a capturing one! So, while I agree that expressiveness-wise, the two solutions are similar (and also I agree that readability-wise the second is probably superior), the performance model is not the same - and if you care about your lambdas being non-capturing, using ugly names is (currently) the only way out, I believe. If shadowing rules are tweaked, you will be able to say: mss.computeIfAbsent(s, s -> s.toLowerCase()); Which is better than the first option (one less throwaway name), and that also gives you the performance model you'll likely want in this case. But I agree that it raises the question of whether the two 's' are really the same or not. Regarding your point that bad names are the fault of the developer - I agree only partially: I don't think there are many sensible name choices for the 's2' variable above. Maurizio On 07/12/16 09:10, Martijn Verburg wrote: > I'll preface this with IANALE (I Am Not A Language Expert), > > TLDR: I've seen direct evidence of not being able to shadow lambda > parameters actually being beneficial for readability. > > ----- > > I currently read a lot of code by developers who are using lambdas and > wanted to add some anecdotal evidence to the shadowing use case. I notice > the JEP author has already stated: > > "It would be desirable to lift this restriction, and allow lambda > parameters (and locals declared with a lambda) to shadow variables defined > in enclosing scopes. (One possible argument against is readability: if > lambda parameters are allowed to shadow, then in the above example, the > identifier 'key' means two different things in the two places where it is > used, and there seem to be no syntactic barrier to separate the two > usages.)" > > --- > > The readability issue is really cropping up a lot with the lambdas code I'm > seeing. Many developers are already following a short hand idiom for lambda > variables e.g. using 'k' instead of 'key', along with some other idioms > that do lessen the readability of lambdas based code in general. This is > clearly not the fault of the language / syntax today, it's more the fault > of the developer! A similar argument can be applied to the proposed 'var' > JEP, as long a developers name their variables properly, readability is > maintained. > > That said, the current status quo of not being able to shadow lambda > parameters is actually forcing developers to think more clearly about > naming and scope, which is generally a good thing. My concern is that if > we are able to shadow lambda parameters this will cause even more confusion > to the reader unless they carefully hover over the section in their > favourite IDE *or* have the 'scope of variables outside of the lambda vs > inside the lambda' concept firmly in their heads (an educational issue). > > ---- > > As a side note, JEPs 300, 301 and 302 are very cool. Anything that improves > type inference and safety automatically for the developer is a welcome > addition and I appreciate how hard it is to get that right internally in > the JVM and in the language. > > > > Cheers, > Martijn > > On 7 December 2016 at 08:37, Remi Forax wrote: > >> I really appreciate this proposal, >> i hit both better disambiguation and shadow of lambda parameters issues >> quite frequently. >> >> For treatment of underscores, >> as i understand, the idea is that you can use '_' as parameter without >> having '_' being entered in the scope of the method, >> i.e. this code will not compile: >> >> void setBar(Bar _) { >> foo(_); >> } >> >> cheers, >> R?mi >> >> ----- Mail original ----- >>> De: "mark reinhold" >>> ?: "maurizio cimadamore" >>> Cc: platform-jep-discuss at openjdk.java.net >>> Envoy?: Mercredi 7 D?cembre 2016 00:50:02 >>> Objet: JEP 302: Lambda Leftovers >>> New JEP Candidate: http://openjdk.java.net/jeps/302 >>> >>> - Mark From maurizio.cimadamore at oracle.com Wed Dec 7 11:18:30 2016 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Wed, 7 Dec 2016 11:18:30 +0000 Subject: JEP 302: Lambda Leftovers In-Reply-To: References: <20161206235002.71F1221109@eggemoggin.niobe.net> Message-ID: <8f97df3d-81e0-816c-e593-e17118318410@oracle.com> On 07/12/16 10:30, Nicolai Parlog wrote: > Hi! > > Great proposal! Especially the underscore is cool, much better than > naming those variables "ignored". I wonder whether I should start using > two underscores now so I can later replace them with a single one. :) I > guess it will be possible to use "_" for multiple parameters? Yes > > I would like to request a feature regarding method references. I like > making non-public methods static to convey the fact that they do not > interact with or even change the state of the object they are called on. > But this conflicts with the ease of method references: > > // `isGenderNeutralName` is an instance method > names.filter(this::isGenderNeutralName) > > vs > > // `isGenderNeutralName` is a static method > names.filter(GenderNeutralNameProcessor::isGenderNeutralName) > > As a consequence I often go back and make it an instance method to keep > the reference readable but it hurts because I give up on an immutability > signal. > > It would be awesome if it were possible to reference a static method in > the same class without repeating the entire class name. Reusing the > `class` keyword seems like an obvious* choice: > > // `isGenderNeutralName` is a static method > names.filter(class::isGenderNeutralName) > > Using Martijn's shorthand, IANALE (I Am Not A Language Expert) so I have > no idea whether this is tractable but it would surely be a nice addition. I see where you are going - a long class name leads to horizontal noise. However, I point out that a similar suggestion could apply to your instance method reference - this::isGenderNeutralName - so, why should I have to say 'this' if there's only one? So I think what people would really like would be to eliminate the noise completely and just say something like this: names.filter(::isGenderNeutralName) But note that this is a harder problem, as now you have a method reference expression that can match both static and instance stuff (which is already the case for unbound method reference, but in that case you can use arity to disambiguate, whereas here you cannot). This also goes hand in hand with being able to disambiguate method reference easily by adding some formal/actual parameter information; if your qualifier expression is shorter, you can in principle have more ambiguities - so it could help having some syntactic support to be able to distinguish between method references with different signature. This topic was also discussed during JDK 8 development but it's not an easy problem to solve; ideally, you'd like to be able to denote formal parameter types in a method reference, as follows: names.filter(::isGenderNeutralName(Object)) But if the method is generic, there could be type-variables in the signature, and it's not clear how we denote those in the method reference expression. Another alternative would be to use 'actual argument types' - so something like: names.filter(::isGenderNeutralName(String)) Where we give the compiler an hint that the first formal should be compatible with a 'String' type. But this looks against the spirit of method references, whose syntax is deliberately decl-site oriented. So, as you can see, optimizing for space in this area could make certain problem worse and it's not clear what can be done to offset such problems. Of course your original proposal of using 'class' to denote 'this type' doesn't introduce additional problem, but feels like a side move to me. Maurizio > > so long ... Nicolai > > > * I am aware that the obvious idea might be also be a terrible idea. > > > > On 07.12.2016 00:50, mark.reinhold at oracle.com wrote: >> New JEP Candidate: http://openjdk.java.net/jeps/302 >> >> - Mark >> From scolebourne at joda.org Wed Dec 7 11:19:52 2016 From: scolebourne at joda.org (Stephen Colebourne) Date: Wed, 7 Dec 2016 11:19:52 +0000 Subject: JEP 301: Enhanced Enums In-Reply-To: References: <20161206234901.64F5221105@eggemoggin.niobe.net> <2000462996.1011073.1481101416087.JavaMail.zimbra@u-pem.fr> <02520562-42ad-c87a-5ddd-9862159ee054@oracle.com> Message-ID: As a motivating example, I considered this design for JSR-310, but had to reject it as this feature didn't exist: interface IntValue { int intValue(); } enum ChronoField { YEAR, MONTH, DAY_OF_MONTH, DAY_OF_WEEK, } Year year = date.get(ChronoField.YEAR); Month month = date.get(ChronoField.MONTH); int dom = date.get(ChronoField.DAY_OF_MONTH); (Note however that this may well have been a bad idea anyway) However, IMO this proposal goes much further than the minimum necessary to support the above, and I cannot support the proposal as it stands. In particular, I am unconvinced that individual enum constants should have visible members - exposing the generic at the constant level is OK, but no more than that makes sense. This is because enums are deliberately intended as a limited feature, with subclasses of enums intended to be non-visible to the application (they are merely a convenience to avoid a switch-on-enum statement). I'd also note that adding visible methods at the constant level will only lead to requests to see each constant implement an interface, effectively creating class-style hierarchies within enum constants - what a mess that would be. (What would be more useful would be a backwards compatible migration path from enums to classes, so that the singleton nature and serialization safety is not lost). Stephen On 7 December 2016 at 10:36, Maurizio Cimadamore wrote: > For the records - here's a more complete example where lack of sharp typing > hurts, I think: > > http://hg.openjdk.java.net/valhalla/valhalla/langtools/file/ce7460995ffc/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Dynamic.java#l41 > > The enum defines all possible kinds of constants which can appear as static > arguments in an invokedynamic call. > > As you can see, many of the methods in this enum are 'partial': they only > make sense for certain constants, but not for others. Currently, the only > way around this, is to declare this method at the root (the enum itself), > and then have the method throw some exception if it's not supposed to be > implemented for certain constants. I believe this idiom is a red herring; > you really don't want the asType/asSymbol be defined for a STRING constant - > and if they weren't, you would get more static type checking back which > would prevent you from calling methods that are not 'supported' rather than > relying to a runtime check. > > Maurizio > > > > On 07/12/16 09:48, Maurizio Cimadamore wrote: >> >> Thanks for the feedback. I personally run into the lack of sharp typing >> several times and seen other people stumbling on it too. >> >> Do you have some example in mind that will break - other than the ones >> listed in the JEP? In my mental model, the kind of surprises this introduces >> are very similar to anonymous inner class types - that is: >> >> new Object() { void m() { } }.m(); >> >> this is legal code because the receiver expression doesn't have type >> Object - but has a sharper type (which can 'see' the additional member). >> This proposal is about doing the same with enums - which accidentally will >> sit well with adding generics (because in that case, the constants will have >> a richer generic type than their parent). >> >> Maurizio >> >> >> On 07/12/16 09:03, Remi Forax wrote: >>> >>> Now, If this proposal is accepted, at least, instead of changing the spec >>> to introduce sharp types for all kind of enums, adding sharp type only for >>> generics enums, >>> it will break no code because generics enum currently do not compile. >> >> > From scolebourne at joda.org Wed Dec 7 11:25:32 2016 From: scolebourne at joda.org (Stephen Colebourne) Date: Wed, 7 Dec 2016 11:25:32 +0000 Subject: JEP 302: Lambda Leftovers In-Reply-To: References: <20161206235002.71F1221109@eggemoggin.niobe.net> <1328186127.992463.1481099865770.JavaMail.zimbra@u-pem.fr> Message-ID: On 7 December 2016 at 10:47, Maurizio Cimadamore wrote: > As a kind of a counter example, consider this: > > Map mss = ... > > String s = "hello"; > mss.computeIfAbsent(s, s2 -> s2.toLowerCase()); > > vs. this: > > mss.computeIfAbsent(s, _ -> s.toLowerCase()); > > The first is a non-capturing lambda - the second is a capturing one! Yuck. I'm afraid this rather confirms my initial opinion that adding _ and removing the shadow restriction are a bad idea. (FWIW, it is very rare for me to have an unused parameter where I find naming it to be a hassle - normally the IDE will choose a sensible name anyway and I just don't worry). I imagine everyone will be in favour of better disambiguation. Stephen > On 07/12/16 09:10, Martijn Verburg wrote: >> >> I'll preface this with IANALE (I Am Not A Language Expert), >> >> TLDR: I've seen direct evidence of not being able to shadow lambda >> parameters actually being beneficial for readability. >> >> ----- >> >> I currently read a lot of code by developers who are using lambdas and >> wanted to add some anecdotal evidence to the shadowing use case. I notice >> the JEP author has already stated: >> >> "It would be desirable to lift this restriction, and allow lambda >> parameters (and locals declared with a lambda) to shadow variables defined >> in enclosing scopes. (One possible argument against is readability: if >> lambda parameters are allowed to shadow, then in the above example, the >> identifier 'key' means two different things in the two places where it is >> used, and there seem to be no syntactic barrier to separate the two >> usages.)" >> >> --- >> >> The readability issue is really cropping up a lot with the lambdas code >> I'm >> seeing. Many developers are already following a short hand idiom for >> lambda >> variables e.g. using 'k' instead of 'key', along with some other idioms >> that do lessen the readability of lambdas based code in general. This is >> clearly not the fault of the language / syntax today, it's more the fault >> of the developer! A similar argument can be applied to the proposed 'var' >> JEP, as long a developers name their variables properly, readability is >> maintained. >> >> That said, the current status quo of not being able to shadow lambda >> parameters is actually forcing developers to think more clearly about >> naming and scope, which is generally a good thing. My concern is that if >> we are able to shadow lambda parameters this will cause even more >> confusion >> to the reader unless they carefully hover over the section in their >> favourite IDE *or* have the 'scope of variables outside of the lambda vs >> inside the lambda' concept firmly in their heads (an educational issue). >> >> ---- >> >> As a side note, JEPs 300, 301 and 302 are very cool. Anything that >> improves >> type inference and safety automatically for the developer is a welcome >> addition and I appreciate how hard it is to get that right internally in >> the JVM and in the language. >> >> >> >> Cheers, >> Martijn >> >> On 7 December 2016 at 08:37, Remi Forax wrote: >> >>> I really appreciate this proposal, >>> i hit both better disambiguation and shadow of lambda parameters issues >>> quite frequently. >>> >>> For treatment of underscores, >>> as i understand, the idea is that you can use '_' as parameter without >>> having '_' being entered in the scope of the method, >>> i.e. this code will not compile: >>> >>> void setBar(Bar _) { >>> foo(_); >>> } >>> >>> cheers, >>> R?mi >>> >>> ----- Mail original ----- >>>> >>>> De: "mark reinhold" >>>> ?: "maurizio cimadamore" >>>> Cc: platform-jep-discuss at openjdk.java.net >>>> Envoy?: Mercredi 7 D?cembre 2016 00:50:02 >>>> Objet: JEP 302: Lambda Leftovers >>>> New JEP Candidate: http://openjdk.java.net/jeps/302 >>>> >>>> - Mark > > From maurizio.cimadamore at oracle.com Wed Dec 7 11:58:54 2016 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Wed, 7 Dec 2016 11:58:54 +0000 Subject: JEP 301: Enhanced Enums In-Reply-To: References: <20161206234901.64F5221105@eggemoggin.niobe.net> <2000462996.1011073.1481101416087.JavaMail.zimbra@u-pem.fr> <02520562-42ad-c87a-5ddd-9862159ee054@oracle.com> Message-ID: Thanks for your feedback. As with the other JEP (Lambda Leftovers) and all JEPs in general, nothing is set in stone (at least not at this stage). I hear that there are some concerns around allowing access to sharp members of an enum constants, but I'd like also to carefully weigh those concerns once a prototype implementation is available for general use. As I said in the other comment to Remi - we had this for anonymous inner classes for ages, but nobody really notices. The goal here is not to suggest people should start using enums to replace class/interface hierarchies, as it is to remove restrictions in the usage of enum constants. I believe there's a path for doing so which does not significantly alter neither source compatibility, binary compatibility nor the user model (you are still free to think that a sharp enum constant E.Foo has type E if you like - as you probably think that new Object() {} has type Object). Of course we can re-evaluate should usability issue pop up in real world examples. Thanks Maurizio On 07/12/16 11:19, Stephen Colebourne wrote: > As a motivating example, I considered this design for JSR-310, but had > to reject it as this feature didn't exist: > > interface IntValue { > int intValue(); > } > > enum ChronoField { > YEAR, > MONTH, > DAY_OF_MONTH, > DAY_OF_WEEK, > } > > Year year = date.get(ChronoField.YEAR); > Month month = date.get(ChronoField.MONTH); > int dom = date.get(ChronoField.DAY_OF_MONTH); > > (Note however that this may well have been a bad idea anyway) > > However, IMO this proposal goes much further than the minimum > necessary to support the above, and I cannot support the proposal as > it stands. In particular, I am unconvinced that individual enum > constants should have visible members - exposing the generic at the > constant level is OK, but no more than that makes sense. This is > because enums are deliberately intended as a limited feature, with > subclasses of enums intended to be non-visible to the application > (they are merely a convenience to avoid a switch-on-enum statement). > > I'd also note that adding visible methods at the constant level will > only lead to requests to see each constant implement an interface, > effectively creating class-style hierarchies within enum constants - > what a mess that would be. (What would be more useful would be a > backwards compatible migration path from enums to classes, so that the > singleton nature and serialization safety is not lost). > > Stephen > > > On 7 December 2016 at 10:36, Maurizio Cimadamore > wrote: >> For the records - here's a more complete example where lack of sharp typing >> hurts, I think: >> >> http://hg.openjdk.java.net/valhalla/valhalla/langtools/file/ce7460995ffc/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Dynamic.java#l41 >> >> The enum defines all possible kinds of constants which can appear as static >> arguments in an invokedynamic call. >> >> As you can see, many of the methods in this enum are 'partial': they only >> make sense for certain constants, but not for others. Currently, the only >> way around this, is to declare this method at the root (the enum itself), >> and then have the method throw some exception if it's not supposed to be >> implemented for certain constants. I believe this idiom is a red herring; >> you really don't want the asType/asSymbol be defined for a STRING constant - >> and if they weren't, you would get more static type checking back which >> would prevent you from calling methods that are not 'supported' rather than >> relying to a runtime check. >> >> Maurizio >> >> >> >> On 07/12/16 09:48, Maurizio Cimadamore wrote: >>> Thanks for the feedback. I personally run into the lack of sharp typing >>> several times and seen other people stumbling on it too. >>> >>> Do you have some example in mind that will break - other than the ones >>> listed in the JEP? In my mental model, the kind of surprises this introduces >>> are very similar to anonymous inner class types - that is: >>> >>> new Object() { void m() { } }.m(); >>> >>> this is legal code because the receiver expression doesn't have type >>> Object - but has a sharper type (which can 'see' the additional member). >>> This proposal is about doing the same with enums - which accidentally will >>> sit well with adding generics (because in that case, the constants will have >>> a richer generic type than their parent). >>> >>> Maurizio >>> >>> >>> On 07/12/16 09:03, Remi Forax wrote: >>>> Now, If this proposal is accepted, at least, instead of changing the spec >>>> to introduce sharp types for all kind of enums, adding sharp type only for >>>> generics enums, >>>> it will break no code because generics enum currently do not compile. >>> From nipa at codefx.org Wed Dec 7 14:19:40 2016 From: nipa at codefx.org (Nicolai Parlog) Date: Wed, 7 Dec 2016 15:19:40 +0100 Subject: JEP 302: Lambda Leftovers In-Reply-To: <8f97df3d-81e0-816c-e593-e17118318410@oracle.com> References: <20161206235002.71F1221109@eggemoggin.niobe.net> <8f97df3d-81e0-816c-e593-e17118318410@oracle.com> Message-ID: <950a86f4-75b2-b4e9-c8f6-3bd641fbb8fd@codefx.org> Hi Maurizio, thank you for considering this, I appreciate it! I can not really speak to the problems you listed but, yes, `::isGenderNeutralName` would of course be nice. On the other hand, `::isGenderNeutralName(String)`, not so much. To developer Joe (like myself) putting blank type names in parenthesis looks very strange. Is there any place in Java, where we do that? > Of course your original proposal of using 'class' to denote 'this > type' doesn't introduce additional problem, but feels like a side > move to me. If the move forward is not possible, maybe sidewards is not so bad. ;) Especially since I assume it would be much cheaper than battling the problems you described. I like `class` because it is somewhat symmetrical to `this`. It has the same length and most IDEs use the same color because both are keywords. They also behave identical when moved into another class, something that can not be said for the explicit type name. I also think that this would not preclude `::isGenderNeutralName` in the future. In that case we're already abandoning `this::isGenderNeutralName` - leaving `class::isGenderNeutralName` behind as well does not seem to add much to that. so long ... Nicolai On 07.12.2016 12:18, Maurizio Cimadamore wrote: > > > On 07/12/16 10:30, Nicolai Parlog wrote: >> Hi! >> >> Great proposal! Especially the underscore is cool, much better >> than naming those variables "ignored". I wonder whether I should >> start using two underscores now so I can later replace them with >> a single one. :) I guess it will be possible to use "_" for >> multiple parameters? > Yes >> >> I would like to request a feature regarding method references. I >> like making non-public methods static to convey the fact that >> they do not interact with or even change the state of the object >> they are called on. But this conflicts with the ease of method >> references: >> >> // `isGenderNeutralName` is an instance method >> names.filter(this::isGenderNeutralName) >> >> vs >> >> // `isGenderNeutralName` is a static method >> names.filter(GenderNeutralNameProcessor::isGenderNeutralName) >> >> As a consequence I often go back and make it an instance method >> to keep the reference readable but it hurts because I give up on >> an immutability signal. >> >> It would be awesome if it were possible to reference a static >> method in the same class without repeating the entire class name. >> Reusing the `class` keyword seems like an obvious* choice: >> >> // `isGenderNeutralName` is a static method >> names.filter(class::isGenderNeutralName) >> >> Using Martijn's shorthand, IANALE (I Am Not A Language Expert) so >> I have no idea whether this is tractable but it would surely be a >> nice addition. > I see where you are going - a long class name leads to horizontal > noise. However, I point out that a similar suggestion could apply > to your instance method reference - this::isGenderNeutralName - so, > why should I have to say 'this' if there's only one? > > So I think what people would really like would be to eliminate the > noise completely and just say something like this: > > names.filter(::isGenderNeutralName) > > > But note that this is a harder problem, as now you have a method > reference expression that can match both static and instance stuff > (which is already the case for unbound method reference, but in > that case you can use arity to disambiguate, whereas here you > cannot). > > This also goes hand in hand with being able to disambiguate method > reference easily by adding some formal/actual parameter > information; if your qualifier expression is shorter, you can in > principle have more ambiguities - so it could help having some > syntactic support to be able to distinguish between method > references with different signature. This topic was also discussed > during JDK 8 development but it's not an easy problem to solve; > ideally, you'd like to be able to denote formal parameter types in > a method reference, as follows: > > names.filter(::isGenderNeutralName(Object)) > > But if the method is generic, there could be type-variables in the > signature, and it's not clear how we denote those in the method > reference expression. > > Another alternative would be to use 'actual argument types' - so > something like: > > names.filter(::isGenderNeutralName(String)) > > > Where we give the compiler an hint that the first formal should be > compatible with a 'String' type. But this looks against the spirit > of method references, whose syntax is deliberately decl-site > oriented. So, as you can see, optimizing for space in this area > could make certain problem worse and it's not clear what can be > done to offset such problems. Of course your original proposal of > using 'class' to denote 'this type' doesn't introduce additional > problem, but feels like a side move to me. > > Maurizio >> >> so long ... Nicolai >> >> >> * I am aware that the obvious idea might be also be a terrible >> idea. >> >> >> >> On 07.12.2016 00:50, mark.reinhold at oracle.com wrote: >>> New JEP Candidate: http://openjdk.java.net/jeps/302 >>> >>> - Mark >>> > -- PGP Key: http://keys.gnupg.net/pks/lookup?op=vindex&search=0xCA3BAD2E9CCCD509 Web: http://codefx.org a blog about software development https://www.sitepoint.com/java high-quality Java/JVM content http://do-foss.de Free and Open Source Software for the City of Dortmund Twitter: https://twitter.com/nipafx From forax at univ-mlv.fr Wed Dec 7 16:21:11 2016 From: forax at univ-mlv.fr (Remi Forax) Date: Wed, 7 Dec 2016 17:21:11 +0100 (CET) Subject: JEP 300: Augment Use-Site Variance with Declaration-Site Defaults In-Reply-To: <20161206234800.4B25021102@eggemoggin.niobe.net> References: <20161206234800.4B25021102@eggemoggin.niobe.net> Message-ID: <1649514303.1256185.1481127671829.JavaMail.zimbra@u-pem.fr> This JEP is very important, it will greatly reduce the need of using wilcards, by example, it will remove a lot of boilerplate in the javadoc of the Stream API making it even readable by undergrads. There is an issue which is not discussed by this JEP, if you declare Optional, it will fail because Optional as a method orElse defined like this: E orElse(E). I wonder if not unlike @SafeVarargs we can introduce an annotation (or a keyword) to say that the E taken as parameter is not stored in the Optional, thus, it's safe to declare Optional. regards, R?mi ----- Mail original ----- > De: "mark reinhold" > ?: "daniel smith" > Cc: platform-jep-discuss at openjdk.java.net > Envoy?: Mercredi 7 D?cembre 2016 00:48:00 > Objet: JEP 300: Augment Use-Site Variance with Declaration-Site Defaults > New JEP Candidate: http://openjdk.java.net/jeps/300 > > - Mark From forax at univ-mlv.fr Wed Dec 7 17:39:40 2016 From: forax at univ-mlv.fr (Remi Forax) Date: Wed, 7 Dec 2016 18:39:40 +0100 (CET) Subject: JEP 302: Lambda Leftovers In-Reply-To: <8f97df3d-81e0-816c-e593-e17118318410@oracle.com> References: <20161206235002.71F1221109@eggemoggin.niobe.net> <8f97df3d-81e0-816c-e593-e17118318410@oracle.com> Message-ID: <1994787106.1285370.1481132380902.JavaMail.zimbra@u-pem.fr> ----- Mail original ----- > De: "Maurizio Cimadamore" > ?: "Nicolai Parlog" , platform-jep-discuss at openjdk.java.net > Envoy?: Mercredi 7 D?cembre 2016 12:18:30 > Objet: Re: JEP 302: Lambda Leftovers > On 07/12/16 10:30, Nicolai Parlog wrote: >> Hi! >> >> Great proposal! Especially the underscore is cool, much better than >> naming those variables "ignored". I wonder whether I should start using >> two underscores now so I can later replace them with a single one. :) I >> guess it will be possible to use "_" for multiple parameters? > Yes >> >> I would like to request a feature regarding method references. I like >> making non-public methods static to convey the fact that they do not >> interact with or even change the state of the object they are called on. >> But this conflicts with the ease of method references: >> >> // `isGenderNeutralName` is an instance method >> names.filter(this::isGenderNeutralName) >> >> vs >> >> // `isGenderNeutralName` is a static method >> names.filter(GenderNeutralNameProcessor::isGenderNeutralName) >> >> As a consequence I often go back and make it an instance method to keep >> the reference readable but it hurts because I give up on an immutability >> signal. >> >> It would be awesome if it were possible to reference a static method in >> the same class without repeating the entire class name. Reusing the >> `class` keyword seems like an obvious* choice: >> >> // `isGenderNeutralName` is a static method >> names.filter(class::isGenderNeutralName) >> >> Using Martijn's shorthand, IANALE (I Am Not A Language Expert) so I have >> no idea whether this is tractable but it would surely be a nice addition. > I see where you are going - a long class name leads to horizontal noise. > However, I point out that a similar suggestion could apply to your > instance method reference - this::isGenderNeutralName - so, why should I > have to say 'this' if there's only one? > > So I think what people would really like would be to eliminate the noise > completely and just say something like this: > > names.filter(::isGenderNeutralName) > > > But note that this is a harder problem, as now you have a method > reference expression that can match both static and instance stuff > (which is already the case for unbound method reference, but in that > case you can use arity to disambiguate, whereas here you cannot). > > This also goes hand in hand with being able to disambiguate method > reference easily by adding some formal/actual parameter information; if > your qualifier expression is shorter, you can in principle have more > ambiguities - so it could help having some syntactic support to be able > to distinguish between method references with different signature. This > topic was also discussed during JDK 8 development but it's not an easy > problem to solve; ideally, you'd like to be able to denote formal > parameter types in a method reference, as follows: > > names.filter(::isGenderNeutralName(Object)) > > But if the method is generic, there could be type-variables in the > signature, and it's not clear how we denote those in the method > reference expression. > > Another alternative would be to use 'actual argument types' - so > something like: > > names.filter(::isGenderNeutralName(String)) > > > Where we give the compiler an hint that the first formal should be > compatible with a 'String' type. But this looks against the spirit of > method references, whose syntax is deliberately decl-site oriented. So, > as you can see, optimizing for space in this area could make certain > problem worse and it's not clear what can be done to offset such > problems. Of course your original proposal of using 'class' to denote > 'this type' doesn't introduce additional problem, but feels like a side > move to me. > My gut feeling is that AClassNameWithALongName::m is far more common than this::m, so we can restrict the meaning of ::m to become equivalent to AClassNameWithALongName::m and not to this::m. As you said in another email, we are now in a better position than during the lambda meetings because we have have a corpus of Java 8 Codes to harvest to see how people use method references. > Maurizio R?mi From john.r.rose at oracle.com Wed Dec 7 19:31:12 2016 From: john.r.rose at oracle.com (John Rose) Date: Wed, 7 Dec 2016 11:31:12 -0800 Subject: JEP 302: Lambda Leftovers In-Reply-To: <1994787106.1285370.1481132380902.JavaMail.zimbra@u-pem.fr> References: <20161206235002.71F1221109@eggemoggin.niobe.net> <8f97df3d-81e0-816c-e593-e17118318410@oracle.com> <1994787106.1285370.1481132380902.JavaMail.zimbra@u-pem.fr> Message-ID: This is a more general problem. What we need, IMO, is this::class or some other goofy-looking syntax to extract the type of an expression, or at the very least the current class. Like typeof but (probably) postfix. ? John > On Dec 7, 2016, at 9:39 AM, Remi Forax wrote: > > My gut feeling is that AClassNameWithALongName::m is far more common than this::m, so we can restrict the meaning of ::m to become equivalent to AClassNameWithALongName::m and not to this::m. From brian.goetz at oracle.com Wed Dec 7 19:42:47 2016 From: brian.goetz at oracle.com (Brian Goetz) Date: Wed, 7 Dec 2016 14:42:47 -0500 Subject: JEP 302: Lambda Leftovers In-Reply-To: References: <20161206235002.71F1221109@eggemoggin.niobe.net> <1328186127.992463.1481099865770.JavaMail.zimbra@u-pem.fr> Message-ID: <7018763c-2f83-8fe7-3780-a07700cd3311@oracle.com> > TLDR: I've seen direct evidence of not being able to shadow lambda > parameters actually being beneficial for readability. > I believe you. Both ways have pros and cons; there are times when it forces you to be clearer, and there are times when it just forces you to crap up your code. The debate over this in the original JSR-335 EG reflected this. Ultimately the decision didn't end up getting made on the basis of one being demonstrably better than the other -- because no one could offer a strong enough argument for either; instead, we hid behind that last refuge of scoundrels, "consistency". Specifically, the scoping rules seemed more consistent the way they were originally written, but no one was really all that comfortable with the decision. > The readability issue is really cropping up a lot with the lambdas code I'm > seeing. Many developers are already following a short hand idiom for lambda > variables e.g. using 'k' instead of 'key', along with some other idioms > that do lessen the readability of lambdas based code in general. Yes, this is very tempting. And for simple lambdas (x -> x + 1), its just fine. But as lambdas get more complicated, developers don't always adjust their habits, as you've observed. The main place where the current scoping rules bite is when the argument of the nested lambda _refers to the same thing_ as the same-named argument in the outer lambda. Such as: Function mapGetter k -> map.computeIfAbsent(k, k -> new PlaceHolder()); Here, both k's are the same thing, so calling the second 'kk' seems gratuitously specific. But this is just one use case; there are others where multiple names would make the code more readable. From brian.goetz at oracle.com Wed Dec 7 20:01:36 2016 From: brian.goetz at oracle.com (Brian Goetz) Date: Wed, 7 Dec 2016 15:01:36 -0500 Subject: JEP 302: Lambda Leftovers In-Reply-To: References: <20161206235002.71F1221109@eggemoggin.niobe.net> Message-ID: <4f82c6a8-96ab-af91-a686-7d76d7772e04@oracle.com> This was explored during JSR-335, and we couldn't really justify it at the time, but it periodically comes around again. This isn't really a fault of method refs; it's more intrinsic to static members (you have the same problem if you want to refer to the lock that guards static synchronized methods, for example, though with your 'class' suggestion, this would be called 'class.class', which is not entirely clear.) Anyway, this is off-topic, so let's get back to the JEPs... On 12/7/2016 5:30 AM, Nicolai Parlog wrote: > // `isGenderNeutralName` is a static method > names.filter(class::isGenderNeutralName) From martijnverburg at gmail.com Wed Dec 7 20:24:47 2016 From: martijnverburg at gmail.com (Martijn Verburg) Date: Wed, 7 Dec 2016 20:24:47 +0000 Subject: JEP 302: Lambda Leftovers In-Reply-To: References: <20161206235002.71F1221109@eggemoggin.niobe.net> <1328186127.992463.1481099865770.JavaMail.zimbra@u-pem.fr> Message-ID: Hi Maurizio, Hmm, interesting. Responses inline: On 7 December 2016 at 10:47, Maurizio Cimadamore < maurizio.cimadamore at oracle.com> wrote: > Well taken points Martin. As you mention, we are aware of the readability > issue, and I think this is an area where it could be beneficial to gather > some data after an initial round of implementation to see where things > stand. As a kind of a counter example, consider this: > > Map mss = ... > > String s = "hello"; > mss.computeIfAbsent(s, s2 -> s2.toLowerCase()); > > vs. this: > > mss.computeIfAbsent(s, _ -> s.toLowerCase()); > > The first is a non-capturing lambda - the second is a capturing one! So, > while I agree that expressiveness-wise, the two solutions are similar (and > also I agree that readability-wise the second is probably superior), the > performance model is not the same - and if you care about your lambdas > being non-capturing, using ugly names is (currently) the only way out, I > believe. If shadowing rules are tweaked, you will be able to say: > > mss.computeIfAbsent(s, s -> s.toLowerCase()); > > Which is better than the first option (one less throwaway name), and that > also gives you the performance model you'll likely want in this case. Agreed, I know we shouldn't focus on syntax, but it does look nicer doesn't it :-). > But I agree that it raises the question of whether the two 's' are really > the same or not. > Regarding your point that bad names are the fault of the developer - I > agree only partially: I don't think there are many sensible name choices > for the 's2' variable above. > I agree finding a good name for s2 is harder, but if the code focuses on whatever that string represents then something like this can work well for naming? String message = "hello"; messages.computeIfAbsent(message, transformedMessage -> transformedMessage.toLowerCase()); Cheers, Martijn > > Maurizio > > > On 07/12/16 09:10, Martijn Verburg wrote: > >> I'll preface this with IANALE (I Am Not A Language Expert), >> >> TLDR: I've seen direct evidence of not being able to shadow lambda >> parameters actually being beneficial for readability. >> >> ----- >> >> I currently read a lot of code by developers who are using lambdas and >> wanted to add some anecdotal evidence to the shadowing use case. I notice >> the JEP author has already stated: >> >> "It would be desirable to lift this restriction, and allow lambda >> parameters (and locals declared with a lambda) to shadow variables defined >> in enclosing scopes. (One possible argument against is readability: if >> lambda parameters are allowed to shadow, then in the above example, the >> identifier 'key' means two different things in the two places where it is >> used, and there seem to be no syntactic barrier to separate the two >> usages.)" >> >> --- >> >> The readability issue is really cropping up a lot with the lambdas code >> I'm >> seeing. Many developers are already following a short hand idiom for >> lambda >> variables e.g. using 'k' instead of 'key', along with some other idioms >> that do lessen the readability of lambdas based code in general. This is >> clearly not the fault of the language / syntax today, it's more the fault >> of the developer! A similar argument can be applied to the proposed 'var' >> JEP, as long a developers name their variables properly, readability is >> maintained. >> >> That said, the current status quo of not being able to shadow lambda >> parameters is actually forcing developers to think more clearly about >> naming and scope, which is generally a good thing. My concern is that if >> we are able to shadow lambda parameters this will cause even more >> confusion >> to the reader unless they carefully hover over the section in their >> favourite IDE *or* have the 'scope of variables outside of the lambda vs >> inside the lambda' concept firmly in their heads (an educational issue). >> >> ---- >> >> As a side note, JEPs 300, 301 and 302 are very cool. Anything that >> improves >> type inference and safety automatically for the developer is a welcome >> addition and I appreciate how hard it is to get that right internally in >> the JVM and in the language. >> >> >> >> Cheers, >> Martijn >> >> On 7 December 2016 at 08:37, Remi Forax wrote: >> >> I really appreciate this proposal, >>> i hit both better disambiguation and shadow of lambda parameters issues >>> quite frequently. >>> >>> For treatment of underscores, >>> as i understand, the idea is that you can use '_' as parameter without >>> having '_' being entered in the scope of the method, >>> i.e. this code will not compile: >>> >>> void setBar(Bar _) { >>> foo(_); >>> } >>> >>> cheers, >>> R?mi >>> >>> ----- Mail original ----- >>> >>>> De: "mark reinhold" >>>> ?: "maurizio cimadamore" >>>> Cc: platform-jep-discuss at openjdk.java.net >>>> Envoy?: Mercredi 7 D?cembre 2016 00:50:02 >>>> Objet: JEP 302: Lambda Leftovers >>>> New JEP Candidate: http://openjdk.java.net/jeps/302 >>>> >>>> - Mark >>>> >>> > From martijnverburg at gmail.com Wed Dec 7 20:30:23 2016 From: martijnverburg at gmail.com (Martijn Verburg) Date: Wed, 7 Dec 2016 20:30:23 +0000 Subject: JEP 302: Lambda Leftovers In-Reply-To: <7018763c-2f83-8fe7-3780-a07700cd3311@oracle.com> References: <20161206235002.71F1221109@eggemoggin.niobe.net> <1328186127.992463.1481099865770.JavaMail.zimbra@u-pem.fr> <7018763c-2f83-8fe7-3780-a07700cd3311@oracle.com> Message-ID: Hi Brian, On 7 December 2016 at 19:42, Brian Goetz wrote: > > > TLDR: I've seen direct evidence of not being able to shadow lambda >> parameters actually being beneficial for readability. >> >> > I believe you. Both ways have pros and cons; there are times when it > forces you to be clearer, and there are times when it just forces you to > crap up your code. The debate over this in the original JSR-335 EG > reflected this. Ultimately the decision didn't end up getting made on the > basis of one being demonstrably better than the other -- because no one > could offer a strong enough argument for either; instead, we hid behind > that last refuge of scoundrels, "consistency". Specifically, the scoping > rules seemed more consistent the way they were originally written, but no > one was really all that comfortable with the decision. Apologies for having missed referencing that original discussion, I really need to be more disciplined about searching the archives first! > The readability issue is really cropping up a lot with the lambdas code I'm >> seeing. Many developers are already following a short hand idiom for >> lambda >> variables e.g. using 'k' instead of 'key', along with some other idioms >> that do lessen the readability of lambdas based code in general. >> > > Yes, this is very tempting. And for simple lambdas (x -> x + 1), its just > fine. But as lambdas get more complicated, developers don't always adjust > their habits, as you've observed. > The main place where the current scoping rules bite is when the argument > of the nested lambda _refers to the same thing_ as the same-named argument > in the outer lambda. Such as: > > Function mapGetter k -> map.computeIfAbsent(k, k -> new > PlaceHolder()); > Ouch, yeah seeing code like that makes me as 'Joe/Jane Java' throw my hands up and hope someone smarter than me understands what's going on. It's why I'm particularly happy with these 3 JEPs overall, it's going to reduce source code confusion. Here, both k's are the same thing, so calling the second 'kk' seems > gratuitously specific. But this is just one use case; there are others > where multiple names would make the code more readable. > Cheers, Martijn From roy.van.rijn at gmail.com Wed Dec 7 21:01:52 2016 From: roy.van.rijn at gmail.com (Roy van Rijn) Date: Wed, 7 Dec 2016 22:01:52 +0100 Subject: JEP 302: Lambda Leftovers In-Reply-To: <20161206235002.71F1221109@eggemoggin.niobe.net> References: <20161206235002.71F1221109@eggemoggin.niobe.net> Message-ID: The only thing about 300, 301 and 302 I don't like initially is the possible danger that could come from shadowing. Not just the fear of loss of readability. For example the following code: Map map = ... String key = "theInitialKey"; map.computeIfAbsent(key, _ -> { String key = "theShadowKey"; // <- delete this return key.length(); }); If you delete that line... nothing fails. The code runs fine, but the behavior has changed, suddenly a different 'key' is used. That is a hidden danger of shadowing. I want my code to break if declarations are removed. There should not be fallbacks to different variables? Roy > Op 7 dec. 2016 om 00:50 heeft mark.reinhold at oracle.com het volgende geschreven: > > New JEP Candidate: http://openjdk.java.net/jeps/302 > > - Mark From maurizio.cimadamore at oracle.com Wed Dec 7 21:49:51 2016 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Wed, 7 Dec 2016 21:49:51 +0000 Subject: JEP 302: Lambda Leftovers In-Reply-To: References: <20161206235002.71F1221109@eggemoggin.niobe.net> Message-ID: <0267b4c6-61e9-33fa-a797-9997474b68c8@oracle.com> On 07/12/16 21:01, Roy van Rijn wrote: > If you delete that line... nothing fails. The code runs fine, but the behavior has changed, suddenly a different 'key' is used. That is a hidden danger of shadowing. I want my code to break if declarations are removed. There should not be fallbacks to different variables? Good point - but how is that different from this: class Test { void m(String s) { class Foo { int getLength() { String s = "Hello!"; //delete this return s.length(); } } System.out.println(new Foo().getLength()); } public static void main(String[] args) { new Test().m("123"); //what does it print? } } Note that this is very similar to your example - you delete a declaration and suddenly you resolve to a different local variable. You can even construct more subtle example where you change overload resolution by removing a declaration in an inner class; so I wouldn't say it's a new issue - it mostly boils down to the (very subjective, I realize) perception of whether the lambda body provides a strong enough clue that you are inside a different scope. In my view, in most case this is fine - as a lambda can only declare local variable if it is a statement lambda with surrounding braces - so syntactic clues are in place. Maurizio From forax at univ-mlv.fr Wed Dec 7 22:28:18 2016 From: forax at univ-mlv.fr (forax at univ-mlv.fr) Date: Wed, 7 Dec 2016 23:28:18 +0100 (CET) Subject: JEP 301: Enhanced Enums In-Reply-To: <02520562-42ad-c87a-5ddd-9862159ee054@oracle.com> References: <20161206234901.64F5221105@eggemoggin.niobe.net> <2000462996.1011073.1481101416087.JavaMail.zimbra@u-pem.fr> <02520562-42ad-c87a-5ddd-9862159ee054@oracle.com> Message-ID: <1596213939.1335221.1481149698100.JavaMail.zimbra@u-pem.fr> > De: "Maurizio Cimadamore" > ?: "Remi Forax" , platform-jep-discuss at openjdk.java.net > Envoy?: Mercredi 7 D?cembre 2016 10:48:44 > Objet: Re: JEP 301: Enhanced Enums > Thanks for the feedback. I personally run into the lack of sharp typing > several times and seen other people stumbling on it too. > > Do you have some example in mind that will break - other than the ones > listed in the JEP? In my mental model, the kind of surprises this > introduces are very similar to anonymous inner class types - that is: > > new Object() { void m() { } }.m(); > > this is legal code because the receiver expression doesn't have type > Object - but has a sharper type (which can 'see' the additional member). > This proposal is about doing the same with enums - which accidentally > will sit well with adding generics (because in that case, the constants > will have a richer generic type than their parent). Abstract enum where introduces as a kind of strawman lambdas (see [1]), and as Stephen said there were intentionally restricted to not be more than that. > > Maurizio R?mi [1] https://youtu.be/pi_I7oD_uGI?t=2041 > > > On 07/12/16 09:03, Remi Forax wrote: >> Now, If this proposal is accepted, at least, instead of changing the spec to >> introduce sharp types for all kind of enums, adding sharp type only for >> generics enums, > > it will break no code because generics enum currently do not compile. From maurizio.cimadamore at oracle.com Thu Dec 8 00:10:03 2016 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Thu, 8 Dec 2016 00:10:03 +0000 Subject: JEP 301: Enhanced Enums In-Reply-To: <1596213939.1335221.1481149698100.JavaMail.zimbra@u-pem.fr> References: <20161206234901.64F5221105@eggemoggin.niobe.net> <2000462996.1011073.1481101416087.JavaMail.zimbra@u-pem.fr> <02520562-42ad-c87a-5ddd-9862159ee054@oracle.com> <1596213939.1335221.1481149698100.JavaMail.zimbra@u-pem.fr> Message-ID: <8ff72aef-4f1d-3895-aa68-2f411862b41f@oracle.com> On 07/12/16 22:28, forax at univ-mlv.fr wrote: >> De: "Maurizio Cimadamore" >> ?: "Remi Forax" , platform-jep-discuss at openjdk.java.net >> Envoy?: Mercredi 7 D?cembre 2016 10:48:44 >> Objet: Re: JEP 301: Enhanced Enums >> Thanks for the feedback. I personally run into the lack of sharp typing >> several times and seen other people stumbling on it too. >> >> Do you have some example in mind that will break - other than the ones >> listed in the JEP? In my mental model, the kind of surprises this >> introduces are very similar to anonymous inner class types - that is: >> >> new Object() { void m() { } }.m(); >> >> this is legal code because the receiver expression doesn't have type >> Object - but has a sharper type (which can 'see' the additional member). >> This proposal is about doing the same with enums - which accidentally >> will sit well with adding generics (because in that case, the constants >> will have a richer generic type than their parent). > > Abstract enum where introduces as a kind of strawman lambdas (see [1]), > and as Stephen said there were intentionally restricted to not be more than that. The video you quote talks about enums inheritance - this JEP in no way affects the way in which enum can (or rather can't) subclass each other (and in fact this is even called out in the JEP). For illustrating the problem this JEP addresses, you don't need fancy hierarchies - all it takes is something simple like this: enum Foo { A() { void a() { ... } }, B, C() { void c() { ... } }; void m() { ... } } Here we have three constants - they all have a method m() - one constant (A) has a method a() and another constant (C) has a method c(). This is not some theoretical example - think of an enum modelling e.g. JVM primitive types - it's not that unreasonable to have operation on certain types but not on others - for instance you can do a conditional jump on an int ( 'if_icmp') - but you cannot do the same on floats (there's no 'if_fcmp'). Or maybe, some operation returns a result of one type in some case, but something of a different result in other cases - for instance, loading an int (iload) gives you an int - loading a float (fload) gives you a float. Now, how do we implement these things if we want to use today's enums? One common (and ugly!) idiom seems to be this: enum Foo { A, B, C; void m() { ... } void a() { switch (this) { case A: //do something default: throw } } void c() { switch (this) { case C: //do something default: throw } } } This has, IMO, several issues: * encapsulation is broken - methods are not declared where they really belong * no static safety - the compiler doesn't blink if you say Foo.B.c(); * readability - every method needs to be turned inside out into a switch The goal of this JEP is to make stuff like this easier to write - and we want to be able to get there so that the extra typing information is there _if you need it_. If you don't care about the sharp types, fine - they won't harm you either (and for the most part you can pretend they don't even exist). Maurizio > >> Maurizio > R?mi > > [1] https://youtu.be/pi_I7oD_uGI?t=2041 > >> >> On 07/12/16 09:03, Remi Forax wrote: >>> Now, If this proposal is accepted, at least, instead of changing the spec to >>> introduce sharp types for all kind of enums, adding sharp type only for >>> generics enums, >>> it will break no code because generics enum currently do not compile. From forax at univ-mlv.fr Thu Dec 8 07:23:28 2016 From: forax at univ-mlv.fr (forax at univ-mlv.fr) Date: Thu, 8 Dec 2016 08:23:28 +0100 (CET) Subject: JEP 301: Enhanced Enums In-Reply-To: <8ff72aef-4f1d-3895-aa68-2f411862b41f@oracle.com> References: <20161206234901.64F5221105@eggemoggin.niobe.net> <2000462996.1011073.1481101416087.JavaMail.zimbra@u-pem.fr> <02520562-42ad-c87a-5ddd-9862159ee054@oracle.com> <1596213939.1335221.1481149698100.JavaMail.zimbra@u-pem.fr> <8ff72aef-4f1d-3895-aa68-2f411862b41f@oracle.com> Message-ID: <1973248818.1360694.1481181808102.JavaMail.zimbra@u-pem.fr> ----- Mail original ----- > De: "Maurizio Cimadamore" > ?: forax at univ-mlv.fr > Cc: platform-jep-discuss at openjdk.java.net > Envoy?: Jeudi 8 D?cembre 2016 01:10:03 > Objet: Re: JEP 301: Enhanced Enums > On 07/12/16 22:28, forax at univ-mlv.fr wrote: >>> De: "Maurizio Cimadamore" >>> ?: "Remi Forax" , platform-jep-discuss at openjdk.java.net >>> Envoy?: Mercredi 7 D?cembre 2016 10:48:44 >>> Objet: Re: JEP 301: Enhanced Enums >>> Thanks for the feedback. I personally run into the lack of sharp typing >>> several times and seen other people stumbling on it too. >>> >>> Do you have some example in mind that will break - other than the ones >>> listed in the JEP? In my mental model, the kind of surprises this >>> introduces are very similar to anonymous inner class types - that is: >>> >>> new Object() { void m() { } }.m(); >>> >>> this is legal code because the receiver expression doesn't have type >>> Object - but has a sharper type (which can 'see' the additional member). >>> This proposal is about doing the same with enums - which accidentally >>> will sit well with adding generics (because in that case, the constants >>> will have a richer generic type than their parent). >> >> Abstract enum where introduces as a kind of strawman lambdas (see [1]), >> and as Stephen said there were intentionally restricted to not be more than >> that. > The video you quote talks about enums inheritance - this JEP in no way > affects the way in which enum can (or rather can't) subclass each other > (and in fact this is even called out in the JEP). For illustrating the > problem this JEP addresses, you don't need fancy hierarchies - all it > takes is something simple like this: > > enum Foo { > A() { void a() { ... } }, > B, > C() { void c() { ... } }; > > void m() { ... } > } > > Here we have three constants - they all have a method m() - one constant > (A) has a method a() and another constant (C) has a method c(). > > This is not some theoretical example - think of an enum modelling e.g. > JVM primitive types - it's not that unreasonable to have operation on > certain types but not on others - for instance you can do a conditional > jump on an int ( 'if_icmp') - but you cannot do the same on floats > (there's no 'if_fcmp'). Or maybe, some operation returns a result of one > type in some case, but something of a different result in other cases - > for instance, loading an int (iload) gives you an int - loading a float > (fload) gives you a float. > > Now, how do we implement these things if we want to use today's enums? > One common (and ugly!) idiom seems to be this: > > enum Foo { > A, > B, > C; > > void m() { ... } > > void a() { > switch (this) { > case A: //do something > default: throw > } > } > > void c() { > switch (this) { > case C: //do something > default: throw > } > } > } > > This has, IMO, several issues: > > * encapsulation is broken - methods are not declared where they really > belong > * no static safety - the compiler doesn't blink if you say Foo.B.c(); > * readability - every method needs to be turned inside out into a switch > > The goal of this JEP is to make stuff like this easier to write - and we > want to be able to get there so that the extra typing information is > there _if you need it_. If you don't care about the sharp types, fine - > they won't harm you either (and for the most part you can pretend they > don't even exist). Why do you want to encode a hierarchy as an enum ? It's OO 101, you create 3 classes, A, B, C, an interface Foo and an abstract class AbstractFoo that contains the code of m() (or maybe use a default method in Foo if like in your example Foo has no field). And your done. Enum were not created to be a short syntax for encoding a hierarchy, and to avoid that, the EG that introduces the Enum feature make it clear by forcing all values of an enum to be typed with the enum type. And as Josh Blosch said in the video, they also wanted to allow to encode what Josh calls 'named function' by allowing abstract enums. Name functions are not useful anymore, because now we have full real lambdas. So there is no reason to use abstract enums anymore, no reason to have enum values with different subclasses even if i agree with you that the syntax for that is short and cool. > > Maurizio R?mi >> >>> Maurizio >> R?mi >> >> [1] https://youtu.be/pi_I7oD_uGI?t=2041 >> >>> >>> On 07/12/16 09:03, Remi Forax wrote: >>>> Now, If this proposal is accepted, at least, instead of changing the spec to >>>> introduce sharp types for all kind of enums, adding sharp type only for >>>> generics enums, > >>> it will break no code because generics enum currently do not compile. From roy.van.rijn at gmail.com Thu Dec 8 08:30:59 2016 From: roy.van.rijn at gmail.com (Roy van Rijn) Date: Thu, 8 Dec 2016 09:30:59 +0100 Subject: JEP 302: Lambda Leftovers In-Reply-To: <0267b4c6-61e9-33fa-a797-9997474b68c8@oracle.com> References: <20161206235002.71F1221109@eggemoggin.niobe.net> <0267b4c6-61e9-33fa-a797-9997474b68c8@oracle.com> Message-ID: Maurizio, > ..snip.. > so I wouldn't say it's a new issue That is not a reason to create more of it ;-) > - it mostly boils down to the (very subjective, I realize) perception of > whether the lambda body provides a strong enough clue that you are inside a > different scope. In my view, in most case this is fine - as a lambda can > only declare local variable if it is a statement lambda with surrounding > braces - so syntactic clues are in place. When talking about local variables inside a lambda with braces, sure, there is a syntactic clue in place. How many lambdas (in the wild) actually have a lot of local variables that are now differently named because of a collision? Is this really a problem worth solving, risking confusion? The JEP is talking about the following example: Map map = new HashMap<>(); int amount = 10; map.computeIfAbsent(amount, amount -> amount += 10); // What is the value of amount? Now there is no syntactic clue to indicate a different scope. Sure, we all know we are modifying a different 'amount' here, but will the average Joe programmer? I'm not so sure. Roy From maurizio.cimadamore at oracle.com Thu Dec 8 10:49:35 2016 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Thu, 8 Dec 2016 10:49:35 +0000 Subject: JEP 302: Lambda Leftovers In-Reply-To: References: <20161206235002.71F1221109@eggemoggin.niobe.net> <0267b4c6-61e9-33fa-a797-9997474b68c8@oracle.com> Message-ID: <75fa86f1-160b-5f5d-c59e-7d5fcb11899f@oracle.com> On 08/12/16 08:30, Roy van Rijn wrote: > Now there is no syntactic clue to indicate a different scope. Sure, we > all know we are modifying a different 'amount' here, but will the > average Joe programmer? I'm not so sure. Totally agree here - in fact this is explicitly called out in the JEP. I think we should hold off judgment and see how this goes in the real world. Certain API idioms (fluent APIs making use of nested lambda, for instance) could definitively take advantage of something like this - but the readability problem is real and should be assessed with some real corpus data. Maurizio From maurizio.cimadamore at oracle.com Thu Dec 8 11:13:19 2016 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Thu, 8 Dec 2016 11:13:19 +0000 Subject: JEP 301: Enhanced Enums In-Reply-To: <1973248818.1360694.1481181808102.JavaMail.zimbra@u-pem.fr> References: <20161206234901.64F5221105@eggemoggin.niobe.net> <2000462996.1011073.1481101416087.JavaMail.zimbra@u-pem.fr> <02520562-42ad-c87a-5ddd-9862159ee054@oracle.com> <1596213939.1335221.1481149698100.JavaMail.zimbra@u-pem.fr> <8ff72aef-4f1d-3895-aa68-2f411862b41f@oracle.com> <1973248818.1360694.1481181808102.JavaMail.zimbra@u-pem.fr> Message-ID: <18248aa2-96ed-ce6d-75b8-b67e1b6e774f@oracle.com> On 08/12/16 07:23, forax at univ-mlv.fr wrote: > Enum were not created to be a short syntax for encoding a hierarchy, and to avoid that, the EG that introduces the Enum feature make it clear by forcing all values of an enum to be typed with the enum type. > And as Josh Blosch said in the video, they also wanted to allow to encode what Josh calls 'named function' by allowing abstract enums. Name functions are not useful anymore, because now we have full real lambdas. So there is no reason to use abstract enums anymore, no reason to have enum values with different subclasses even if i agree with you that the syntax for that is short and cool. One thing is to say no to enum subclassing. I agree that is the right decision - when you want to operate on enum constants, you should live in a world where the universe of constants if known statically, otherwise it all falls down. Another thing is to say that the extra information we have about enum constants at compile-time should be thrown away. That is the part of your argument I disagree with - and I'm having troubles seeing what 'erasing' the enum constant type buys you. On the other hand, not erasing the type _does_ buy you something; in addition to the examples already mentioned, another common use case is to be able to reuse code inside enums: http://stackoverflow.com/questions/15523925/how-to-reuse-code-in-multiple-enum Of course, if your position is that nobody should ever use bodies in enum constants, then I think there's nothing for you to look at here :-) Maurizio From maurizio.cimadamore at oracle.com Thu Dec 8 18:56:29 2016 From: maurizio.cimadamore at oracle.com (Maurizio Cimadamore) Date: Thu, 8 Dec 2016 18:56:29 +0000 Subject: JEP 301: Enhanced Enums In-Reply-To: <20161206234901.64F5221105@eggemoggin.niobe.net> References: <20161206234901.64F5221105@eggemoggin.niobe.net> Message-ID: <31f5842e-58a0-96ef-d3f4-3591e9555d93@oracle.com> In response to some of the comments, I've updated the example in the initial section of the JEP; the new example is less convoluted, and shows the benefits of the enhancements proposed in this JEP in a more direct way. Thanks Maurizio On 06/12/16 23:49, mark.reinhold at oracle.com wrote: > New JEP Candidate: http://openjdk.java.net/jeps/301 > > - Mark From john.r.rose at oracle.com Thu Dec 8 21:12:14 2016 From: john.r.rose at oracle.com (John Rose) Date: Thu, 8 Dec 2016 13:12:14 -0800 Subject: JEP 301: Enhanced Enums In-Reply-To: <1973248818.1360694.1481181808102.JavaMail.zimbra@u-pem.fr> References: <20161206234901.64F5221105@eggemoggin.niobe.net> <2000462996.1011073.1481101416087.JavaMail.zimbra@u-pem.fr> <02520562-42ad-c87a-5ddd-9862159ee054@oracle.com> <1596213939.1335221.1481149698100.JavaMail.zimbra@u-pem.fr> <8ff72aef-4f1d-3895-aa68-2f411862b41f@oracle.com> <1973248818.1360694.1481181808102.JavaMail.zimbra@u-pem.fr> Message-ID: <26957620-F8AD-4964-8A1F-76544B92D947@oracle.com> On Dec 7, 2016, at 11:23 PM, forax at univ-mlv.fr wrote: > > Name functions are not useful anymore, because now we have full real lambdas. There is still a big place for named function enums. Lambdas let you say "here is a plus operator" but not "here is the plus operator which is abelian with unit 0". Enums can fill that gap, for now. ? John From forax at univ-mlv.fr Thu Dec 8 22:36:24 2016 From: forax at univ-mlv.fr (forax at univ-mlv.fr) Date: Thu, 8 Dec 2016 23:36:24 +0100 (CET) Subject: JEP 301: Enhanced Enums In-Reply-To: <26957620-F8AD-4964-8A1F-76544B92D947@oracle.com> References: <20161206234901.64F5221105@eggemoggin.niobe.net> <2000462996.1011073.1481101416087.JavaMail.zimbra@u-pem.fr> <02520562-42ad-c87a-5ddd-9862159ee054@oracle.com> <1596213939.1335221.1481149698100.JavaMail.zimbra@u-pem.fr> <8ff72aef-4f1d-3895-aa68-2f411862b41f@oracle.com> <1973248818.1360694.1481181808102.JavaMail.zimbra@u-pem.fr> <26957620-F8AD-4964-8A1F-76544B92D947@oracle.com> Message-ID: <734789646.1732677.1481236584928.JavaMail.zimbra@u-pem.fr> ----- Mail original ----- > De: "John Rose" > ?: forax at univ-mlv.fr > Cc: "Maurizio Cimadamore" , platform-jep-discuss at openjdk.java.net > Envoy?: Jeudi 8 D?cembre 2016 22:12:14 > Objet: Re: JEP 301: Enhanced Enums > On Dec 7, 2016, at 11:23 PM, forax at univ-mlv.fr wrote: >> >> Name functions are not useful anymore, because now we have full real lambdas. > > There is still a big place for named function enums. Lambdas let you say "here > is a plus operator" but not "here is the plus operator which is abelian with > unit 0". Enums can fill that gap, for now. you mean something like: interface Group { BinaryOperator binOp(); T identity(); boolean is(Characteritics characteristics); .. } enum Op implements Group { PLUS(Integer::sum, 0, Characteritics.ABELIAN) ; ... } public static Optional reduce(Listlist, Group group) { if (group.is(Characteritics.ABELIAN) && list.size() > ...) { return Optional.of(parallelReduce(list, group.identity(), group.binOp())); } return foldLeft(list, group.binOp()); } ... reduce(List.of(1, 2, ...), Op.PLUS); but you can simply write static class Op implements Group { public static final Group PLUS = new Op(Integer::sum, 0, Characteritics.ABELIAN); ... } > > ? John R?mi From john.r.rose at oracle.com Thu Dec 8 23:01:18 2016 From: john.r.rose at oracle.com (John Rose) Date: Thu, 8 Dec 2016 15:01:18 -0800 Subject: JEP 301: Enhanced Enums In-Reply-To: <734789646.1732677.1481236584928.JavaMail.zimbra@u-pem.fr> References: <20161206234901.64F5221105@eggemoggin.niobe.net> <2000462996.1011073.1481101416087.JavaMail.zimbra@u-pem.fr> <02520562-42ad-c87a-5ddd-9862159ee054@oracle.com> <1596213939.1335221.1481149698100.JavaMail.zimbra@u-pem.fr> <8ff72aef-4f1d-3895-aa68-2f411862b41f@oracle.com> <1973248818.1360694.1481181808102.JavaMail.zimbra@u-pem.fr> <26957620-F8AD-4964-8A1F-76544B92D947@oracle.com> <734789646.1732677.1481236584928.JavaMail.zimbra@u-pem.fr> Message-ID: True. The use case I have in mind identifies the ops as intrinsics. The enum index ties to code generation tables. ? John > On Dec 8, 2016, at 2:36 PM, forax at univ-mlv.fr wrote: > > ----- Mail original ----- >> De: "John Rose" >> ?: forax at univ-mlv.fr >> Cc: "Maurizio Cimadamore" , platform-jep-discuss at openjdk.java.net >> Envoy?: Jeudi 8 D?cembre 2016 22:12:14 >> Objet: Re: JEP 301: Enhanced Enums > >>> On Dec 7, 2016, at 11:23 PM, forax at univ-mlv.fr wrote: >>> >>> Name functions are not useful anymore, because now we have full real lambdas. >> >> There is still a big place for named function enums. Lambdas let you say "here >> is a plus operator" but not "here is the plus operator which is abelian with >> unit 0". Enums can fill that gap, for now. > > you mean something like: > interface Group { > BinaryOperator binOp(); > T identity(); > boolean is(Characteritics characteristics); > .. > } > > enum Op implements Group { > PLUS(Integer::sum, 0, Characteritics.ABELIAN) > ; > ... > } > > public static Optional reduce(Listlist, Group group) { > if (group.is(Characteritics.ABELIAN) && list.size() > ...) { > return Optional.of(parallelReduce(list, group.identity(), group.binOp())); > } > return foldLeft(list, group.binOp()); > } > ... > reduce(List.of(1, 2, ...), Op.PLUS); > > > but you can simply write > > static class Op implements Group { > public static final Group PLUS = new Op(Integer::sum, 0, Characteritics.ABELIAN); > ... > } > >> >> ? John > > R?mi From brian.goetz at oracle.com Wed Dec 14 22:30:34 2016 From: brian.goetz at oracle.com (Brian Goetz) Date: Wed, 14 Dec 2016 17:30:34 -0500 Subject: Update on JEP-286 (Local Variable Type Inference) In-Reply-To: <07927e73-0473-3a20-5646-1f2d698d2f86@oracle.com> References: <07927e73-0473-3a20-5646-1f2d698d2f86@oracle.com> Message-ID: <1a5eef01-ee93-3e45-791b-9af4ac08372d@oracle.com> > PROVIDING FEEDBACK > > To keep the signal-to-noise ratio to an acceptable level, we're asking > people to provide (constructive) feedback through the following > survey, whose results will be made public. > > https://www.surveymonkey.com/r/FBT9WYP I have closed the survey. The survey responses are available in full here: https://www.surveymonkey.com/results/SM-6X5CDVJF/ We received 25 responses. The largest bucket was "general support", either for the feature in general, or the specific choices about syntax (var only). The next largest bucket was the "Saddenz, no val" bucket; we knew that some people would be disappointed by this choice. (Including one elaborate plea for "val only.") Along with a few "please reconsider, I don't like it." Questions included: Q: Will "final var" work? A: Yes. Q: Can we have a Lisp-inspired "let" expression? A: Maybe someday, but that's not the focus of this exploration. Q: How does it work with boxing? If I say "var x = 42", what do we infer? A: The type of `42` is `int`, so we infer `x` as `int`. Boxing conversions only comes into play when strictly needed (assigning to a reference type, or in method invocations), and is not needed here. Q: Was a simple IDE plugin considered? A: Not by us (we don't control all the Java IDEs.) Q: Did you consider reusing just the "final" keyword? A: Yes.