VERSION 2: Re: Proposal: Type inference for variable definition/initialization using the 'auto' keyword.
Tim Lebedkov
tim.lebedkov at googlemail.com
Sun May 24 10:55:55 PDT 2009
Hello,
here is an updated proposal that also deals with two cases pointed to
by Maurizio Cimadamore <maurizio.cimadamore at sun.com>
and some cases found after more careful reading of the JLS
The cases are:
- union types
- cyclic variable references
- null type
- multiple variable declarations
- array declarations
- declaration without initialization
Regards
--Tim
Type inference for variable definition/initialization using the 'auto'
keyword (Version 2).
AUTHOR(S): Tim Lebedkov
OVERVIEW
Provide a two sentence or shorter description of these five aspects of
the feature:
FEATURE SUMMARY: Should be suitable as a summary in a language tutorial.
This proposal addresses the addition of type inference for
variable definitions to the Java programming language using the 'auto'
keyword instead of specific type name.
For example, consider the following assignment statement:
Map<String, List<String>> anagrams = new HashMap<String, List<String>>();
This is rather lengthy, so it can be replaced with this:
auto anagrams = new HashMap<String, List<String>>();
and anagrams is automatically typed as HashMap<String, List<String>>
MAJOR ADVANTAGE: What makes the proposal a favorable change?
Generics have had a tremendously positive impact on type safety in the
Java programming language. They have made it possible to provide
static guarantees about the type of instances used by other classes,
preventing entire classes of runtime errors from occurring. However,
generics have added complexity to Java, making the code far more
verbose and occasionally difficult to read. Although solving this
problem is well outside the scope of this proposal, a limited form of
type inference would remove unnecessary redundancy from the language.
Even without generics it seems unnecessary to duplicate type names for
simple variable definitions/assignments like:
Integer a = new Integer(1023);
MAJOR BENEFIT: Why is the platform better if the proposal is adopted?
Less code and no duplication has a positive impact on many things:
- faster typing/faster code changes
- easier code changing without IDE assistance
- code versioning diffs are more clear
MAJOR DISADVANTAGE: There is always a cost.
- it could be harder to read the code.
- auto will be a keyword and may break some old code
ALTERNATIVES: Can the benefits and advantages be had some way without
a language change?
no
EXAMPLES
SIMPLE EXAMPLE: Show the simplest possible program utilizing the new feature.
1. simple assignment
Map<String, List<String>> a = new HashMap<String, List<String>>();
becomes
auto a = new HashMap<String, List<String>>();
2. auto in for
List<String> list = ...
for (auto s: list)
...
3. auto for a final variable
final ArrayList<String> list = new ArrayList<String>();
becomes
final auto list = new ArrayList<String>();
4. class field definition
class A {
String a = "";
}
becomes
class A {
auto a = "";
}
ADVANCED EXAMPLE: Show advanced usage(s) of the feature.
auto i = 5 + 3; // same as "int i = 5 + 3"
auto i = 5 + 3L; // same as "long i = 5 + 3L"
for (auto entry : (new HashMap<Integer, String>>).entrySet()) { }
DETAILS
SPECIFICATION: Describe how the proposal affects the grammar, type
system, and meaning of expressions and statements in the Java
Programming Language as well as any other known impacts.
Informally, the specification adds syntax to replace the type definition
in variable definitions with assignments by 'auto'. The type of the variable
is automatically determined.
The use of the null literal for initialization is not permitted.
The following code should result in an error:
auto value = null; // compile-time error. The type of value cannot
// be determined.
A cast to a type could be used used to avoid a compile-time error:
auto value = (String) null; // OK
Cyclic references in initialization should also result in compiler errors:
Example:
class A {
static auto a = B.b; // compile-time error. Cyclic reference.
}
class B {
static auto b = A.a; // compile-time error. Cyclic reference.
}
The type of a variable defined using "auto" should be determined at
the time of definition. Finding the right type as replacement for
"auto" does not depend on subsequent statements.
Example:
auto a; // compile-time error. The type of "a" cannot be determined.
a = 2;
Example:
auto a = 2;
a = 2.0f; // compile-time error. The type of "a" is "int"
All variables declared using the same "auto" statement are of the
same type. The type is determined by the first variable in the list
with an initialization expression.
Example:
auto a, b = 2; // OK. The type of "a" and "b" is "int".
Example:
auto a, b; // compile-time error. The type cannot be determined.
Example:
auto a = 2, b = "tree"; // compile-time error. Different types for "a" and "b".
An array initialization expressions cannot be used with "auto":
auto a = {2, 0, 0, 0}; // compile-time error.
Java allows to place brackets for array type declaration either
after the variable name or after the type name. Similar rules apply also
to "auto":
auto a[] = new int[] {}; // OK. "a" is of type "int[]"
auto b[] = new int[2][3]; // OK. "b" is of type "int[][]"
auto c[] = 5; // compile-time error. "int" is not an array type
auto d[][] = new int[4]; // compile-time error. "int[]" cannot be
casted to "int[][]"
COMPILATION: How would the feature be compiled to class files? Show
how the simple and advanced examples would be compiled. Compilation
can be expressed as at least one of a desugaring to existing source
constructs and a translation down to bytecode. If a new bytecode is
used or the semantics of an existing bytecode are changed, describe
those changes, including how they impact verification. Also discuss
any new class file attributes that are introduced. Note that there are
many downstream tools that consume class files and that they may to be
updated to support the proposal!
The resulting bytecode would be identical to bytecode generated by the
same code with the types inferred.
TESTING: How can the feature be tested?
The proposed construct can be tested by writing a number of statements
that construct instances using
inferred types. These instances can then be assigned to variables and
fields of specific types, and passed to
methods that expect specific types. These tests should compile and run
as expected:
auto set = new SortedSet<String>();
set.add("A");
set.add("B");
set.add("C");
// verify that set contains "A", "B", "C".
LIBRARY SUPPORT: Are any supporting libraries needed for the feature?
No library support is required, although libraries can be rewritten to
take advantage of the new feature.
REFLECTIVE APIS: Do any of the various and sundry reflection APIs need
to be updated? This list of reflective APIs includes but is not
limited to core reflection (java.lang.Class and java.lang.reflect.*),
javax.lang.model.*, the doclet API, and JPDA.
No reflective APIs need to be changed.
OTHER CHANGES: Do any other parts of the platform need be updated too?
Possibilities include but are not limited to JNI, serialization, and
output of the javadoc tool.
No other parts of the platform need to be updated.
MIGRATION: Sketch how a code base could be converted, manually or
automatically, to use the new feature.
Libraries can be rewritten to take advantage of this feature, but it
is not imperative that they do so.
COMPATIBILITY
This change is backwards incompatible on the source code level.
BREAKING CHANGES: Are any previously valid programs now invalid? If
so, list one.
All programs that use auto as a name for an identifier would become invalid.
EXISTING PROGRAMS: How do source and class files of earlier platform
versions interact with the feature? Can any new overloadings occur?
Can any new overriding occur?
The feature is completely transparent to the class files. Class files
do not contain
any information about the variables declared using 'auto'.
REFERENCES
[1] Thanks to Jeremy Manson (his proposal served as a template for this one)
http://mail.openjdk.java.net/pipermail/coin-dev/2009-February/000009.html
[2] Jaako Jarvi and Bjarne Stroustrup. Decltype and auto (revision 3).
Paper N1607,
JTC1-SC22/WG21, February 17 2004. Online: http://www.open-std.org/jtc1/
sc22/wg21/docs/papers/2004/n1607.pdf; same as ANSI NCITS/J16 04-0047.
[3] James Gosling, Bill Joy, Guy Steele, and Gilad Bracha. The Java
Language Specification, 3rd Edition.
Addison Wesley, 2004.
EXISTING BUGS: Please include a list of any existing Sun bug ids
related to this proposal.
6242254, 4983159, 6368076
URL FOR PROTOTYPE (optional):
none
On Thu, May 21, 2009 at 7:00 PM, Per Bothner <per at bothner.com> wrote:
> On 05/21/2009 09:45 AM, Tim Lebedkov wrote:
>>
>> On Wed, May 20, 2009 at 11:52 AM, Maurizio Cimadamore
>> <Maurizio.Cimadamore at sun.com> wrote:
>>>
>>> often JavaFX users complain about the impossibility of writing code like:
>>>
>>> var x = "Hello";
>>> x = 1; //type-error here, Integer cannot be assigned to String
>>
>> In my opinion the JavaFX implementation is better: it is easier to
>> implement and
>> more type safe. I'll add this example to the proposal.
>
> The problem is that gets into awkwardness of the "most specific type"
> issues. For example:
>
> var x = 0; // Inferred to be integer
> x = x + 0.1; // Oops
>
> What we'd like to do is infer the type to be the "union type"
> (or most specific shared super-type) of all the assignments to
> a variable. This of course requires all the assignments to be
> visible, which is why we made the default visibility in JavaFX
> "script-local" (rather than package-local as in Java).
>
> An increment as above would normally cause a cycle (because the
> variable is used in the RHS of the assignment), but it is
> possible to special-case increments (and appending), and that
> would seem worthwhile.
>
> (Conditional expressions also use "union types".)
>
> Unfortunately, we haven't had time to implement a better
> type inference algorithm.
> --
> --Per Bothner
> per at bothner.com http://per.bothner.com/
>
More information about the coin-dev
mailing list