Name: bsC130419 Date: 05/15/2001
Currently the Java Language Specification (JLS) requires you to specify the type
of a variable when the variable is declared. This is often annoying, especially
in combination with casts. For example, to iterate over a map:
Map map = getSomeMap();
Iterator iter = map.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry entry = (Map.Entry) iter.next();
MyTableValue value = (MyTableValue) entry.getValue();
...;
}
Here the variable declarations of 'entry' and 'value' need to specify the type
twice. A simple extension to the JLS would be to be able to introduce variables
without specifying the type. For example:
let map = getSomeMap();
let iter = map.entrySet().iterator();
while (iter.hasNext()) {
let entry = (Map.Entry) iter.next();
let value = (MyTableValue) entry.getValue();
...;
}
This makes the code easier to read, type, and change due to less duplication of
information. A variable declared using the 'let' construct will take its type
from the initializer value expression.
Implementation effort is minimal. I've finished a basic implementation of this
in my copy of the Jikes compiler in less than 4 hours (without any prior
knowledge of the Jikes source code). No changes are necessary to the JVM, the
.class file format, or the Java APIs.
Restrictions:
1) A variable introduced using the let statement _must_ have an initializer
statement so its type can be determined.
2) A variable introduced using the let statement _cannot_ have an array
initializer as determining the type for array initializers is difficult.
Options:
1) Instead of introducing a new keyword 'let' reuse the 'final' keyword. This
slightly changes the semantics (the variable is final) but avoids having to
introduce a keyword.
2) Allow 'let' to be used in expressions:
public int surfaceArea(int x1, int y1, int x2, int y2) {
return let dx = x2 - x1,
dy = y2 - y1,
in dx * dy;
}
This uses an additional keyword 'in'. 'dx' and 'dy' are only visible inside
the expression. Instead of 'in' the 'do' keyword could be reused.
3) Allow 'let' to be used as part of a member declaration in an interface or
class.
Note: My implementation follows the restrictions and does not implement any of
the options.
Other RFEs:
Generics (JSR-014) looks like they would reduce the need for 'let'. Consider
the following example:
Map<String, Integer> map = getSomeMap();
Iterator<Map<String, Integer>.Entry> iter = map.entrySet().iterator();
while (iter.hasNext()) {
Map<String, Integer>.Entry entry = iter.next();
...;
}
Very wordy indeed! At least no casts were necessary. Compare this with the
'let' version:
let map = getSomeMap();
let iter = map.entrySet().iterator();
while (iter.hasNext()) {
let entry = iter.next();
...;
}
No casts and no complex type declarations. The code is still fully type-checked
by the compiler without bothering the programmer with the need for type
declarations.
(Review ID: 124038)
======================================================================