Fwd: Update on JEP-286 (Local Variable Type Inference)

Martijn Verburg martijnverburg at gmail.com
Tue Dec 6 23:51:49 UTC 2016


Please disseminate across your communities / organisations.  Thanks!

Cheers,
Martijn

---------- Forwarded message ----------
From: Brian Goetz <brian.goetz at oracle.com>
Date: 6 December 2016 at 19:37
Subject: Update on JEP-286 (Local Variable Type Inference)
To: platform-jep-discuss at openjdk.java.net


[ 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!


More information about the adoption-discuss mailing list