Dangerous new Language Features: Indexing access syntax for Lists and Maps
In this blog I'll talk about a new language feature proposed for Java7 by project coin and the problems I see with it.
Maybe it is time to buy those Scala books and take a deep dive...
Who has ever seen this construct before?
int i, j; i = j = 10;
Will this even compile? Ow, of course it will: the value of an assignment is the right hand side of the assignment and thus it can be reassigned to another variable. In my professional career I have only ever encountered such statements in frameworks written by people that are too smart for their own good. It takes a few seconds to sink in and then you realize that both variables will be set to the same value, no problem!
I don't see the value of this "feature" of the Java language: splitting it over two lines will not harm the compiler, the JVM and definitely not the poor programmer that needs to read the lines of code after the genius that originally wrote them has left the building.
Recently I read a the proposal for a new feature in Jdk7 that will provide indexing access for Lists and Maps. The normal examples are quite easy to read or write:
names = ... names = "Maarten Winkels"; // -> names.set(0, "Maarten Winkels"); String you = names; // -> names.get(1); Map residence = ... residence["Maarten Winkels"] = "India"; // -> residence.put("Maarten Winkels", "India"); String r = residence["Koningin Beatrix"]; // -> residence.get("Koningin Beatrix");
This looks good at first sight. It is all syntax sugar, so nothing really fancy going on, but the code is shorter and easier to read, while it still adheres to a lot of good things like type safety (the list is still a list) and polymorphism (the index operators are defined on core Java interfaces and will work on every implementation).
The I read the more advanced example and something began to stir in my mind.
residence["Maarten Winkels"] = residence["Koningin Beatrix"] = "Palace";
So what does this line of code tell you? You might have to look it over just one more time before you give your answer.
At first, your conclusion might be that the Queen ("=Koningin") and I are going to share a Palace. This is what the normal "double" assignment means, right? Both variables will have the same value. Think again! The queen is going to move to a Palace and I'm left with wherever she lived before (which might be still oke...)! The is because the put operation on a Map actually returns the previously stored value. The code translates to:
residence.put("Maarten Winkels", residence.put("Koningin Beatrix", "Palace"));
Which should make it clear that I'm going to have a different residence than the Queen. If there was no value associated to the Queen in the Map, put returns null and I might even be homeless!
I think this is a very bad feature. One might argue that the "double" assignment feature is not used very often, but my feeling is that a language should be as consistent to a reader as it can be and this to me clearly deviates from that path.
How can we solve this problem while maintaining consistency and backwards compatibility? I think that is really hard: We could make the assignment operator from the proposal not return a value (and return void in stead, making it impossible to do a "double" assignment. This would, however, not be consistent with a normal assignment operator.
Should this caveat prevent this otherwise nice new feature to come to the Java language? I think we should really look at what we are trying to achieve with Java7. For me it would be more important to enable Java developers to easily read and fix existing code bases. If they can save a few characters, that is fine, but overall understandability of the language and ability to fix common bugs with new constructs (e.g. using closures for save resource usage) is far more important. Java (the language) should not add features just to be able to bring down the LoC of a program to the same level as Groovy or Ruby: For a large application, those are very short term goals. There are many options to integrate with these languages on the JVM anyway, so why do we need the Java language to compete with them?