Update on JEP-286 (Local Variable Type Inference)

[ 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<User> users = db.getUsers(); Map<User, Address> 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!