Skip to main content

Type inference of local variables

Posted by forax on December 11, 2006 at 2:56 AM PST

For an average duke, the big difference between a language like
PHP, Python and Java is that you have to declare the type
of the variables.
In general, it's not a big beal for a statement
like this one

  foo=new Foo();

to declare the type and so write it like that
  Foo foo=new Foo();

The advantage of declaring the type Foo is that
the compiler won't let you use foo in
cases not allowed.

But with the introduction of generics,
a creation of collection like this one

  HashMap<String, List<Account>> accounts=
    new HashMap<String, List<Account>>();

leads to a stupid duplication of lot of
characters and obfuscate the code.

I'm not the first to write about that,
this was discussed when generics was introduced
(see by example an artima forum thread about
generics
and the DRY principle
)


Today we have at least two concurrent proposals to
avoid to write a type twice: shorter instance creation or
type inference of local variable.

Shorter instance creation

The first one come from the
last
blog entry of Danny Coward
about jdk 1.7, in slide 38
under the title "shorter instance creation", you can find this example:

 LinkedList<String> list=new();

The type used by new is the type of the declared variable.
I'm not a big fan of this proposal because it is focus on
object creation and not on variable declaration.
This proposal doesn't simplify a JEE sample like this one:

  List<Employee> employeeList=
    entityManager.findAll(Employee.class);

Even if, i agree with the fact that the type of the variable is
more important that the type used by the new,
i prefer the second proposal.

Type inference of local variables

The other proposal is to add a way to declare a local variable
without explicitely mention its type and let the compiler infer it
using the right hand side of the assignation.


This second poposal is not new, i've found an old RFE
in the database that describes it :

bug 4459053
.
This RFE was closed but i was before tiger so before
the JLS3 describes how a type can be infered from an expression.


The RFE proposes to add a keyword 'let'

 let list=new LinkedList<String>();

The spec of C# 3.0 will use the same mecanism
but with the kerword 'var' instead of 'let'.

 var list=new LinkedList<String>();

James Gosling describes in a blog
entry
another possible syntax,
using ':=' instead. This syntax has the great advantage to not
introduce a new keyword.

 list:=new LinkedList<String>();
employeeList:=entityManager.findAll(Employee.class);

Using the james's syntax, the grammar of the JLS can be patch
by adding a new production DRYVariableDeclaratorRest :

  BlockStatement :
        LocalVariableDeclarationStatement
        ClassOrInterfaceDeclaration
        [Identifier :] Statement

  LocalVariableDeclarationStatement:
        [final] Type VariableDeclarators ;

  VariableDeclarators:
        VariableDeclarator { , VariableDeclarator }

  VariableDeclaratorsRest:
        VariableDeclaratorRest { , VariableDeclarator }

  VariableDeclarator:
        Identifier (VariableDeclaratorRest | DRYVariableDeclaratorRest)

  VariableDeclaratorRest:
        {[]} [  =   VariableInitializer]

  DRYVariableDeclaratorRest:
        := VariableInitializer

You can verify that it is integrated smoothly
with the other rule and that such a local variable
can be declared final or can have annotations.

Update: december, 15ht, the following idea
is stupid, sorry.

There is a small gotcha with the foreach loop.
If one decide to just omit to declare the type like this:

 for(s:list) {
   System.out.println(s);
}

the grammar will contain a case where an identifier can be
a type or a variable (like in C++). To avoid that, i propose
to introduce another colon to disambiguiate the grammar.
Thus a code that declare a local variable in a foreach loop
should be like this:

 for(s::list) {
   System.out.println(s);
}

The grammar with a production that manages infered local variables.

ForVarControl:
        [final] [Annotations] ForVarDeclarator

ForVarDeclarator:
        Type Identifier ForVarControlRest
        Identifier :: Expression

ForVarControlRest:
        VariableDeclaratorsRest ;  [Expression]  ;  [ForUpdate]
        : Expression

I hope the next jdk will include more than a
shorter instance creation syntax.


I wait your comment.


Rémi

Related Topics >>