This is a genuine street sign from Nelson, New Zealand. But perhaps its telling us that AJAX really is a dead end and we need something better?! Or that now we've started using AJAX there's no escape?!!
(Well I found it funny anyway ;-)
This is a genuine street sign from Nelson, New Zealand. But perhaps its telling us that AJAX really is a dead end and we need something better?! Or that now we've started using AJAX there's no escape?!!
(Well I found it funny anyway ;-)
So, the big download Firefox world record attempt has started in a farce. Why? Because of a complete lack of understanding of and planning for date and time issues!
The 'download day' has been advertised as 17th June 2008. But there is no clear information as to when on the 17th June. So when would you assume?
Personally, I would naturally assume the 24 hours starting at midnight UTC. But no. The 24 hour period actually starts at 10am Pacific Daylight Time. Crazy!!!
The recriminations on this have already started. The main complaints include bad planning, American focus and plain stupidity. It already looks like quite a few people assume that the release has been delayed. Some appear to have given up on the download.
Again with dates and times the message is clear - time zones are a pain, but you can't ignore them!
For many moons there have been discussions about what we need to do to 'fix' Java. But what might the language look like if we applied all the possible fixes?
Many (all?) of the ideas for creating a 'better Java' are not new, and have been talked about many times over the years. Ola Bini produced one list, which included no primitives, enhanced generics (no angle brackets), closures, method references, implementation in interfaces, some type inference, no checked exceptions and non-null variables. This is a good list and mirrors many of the discussions that have been held on this blog.
Of course, this JavaNG/Java3/BetterJava language doesn't exist does it?
Well, perhaps it does.
The Fan Fantom programming language is one I've been watching for a couple of months since it first launched its website.
Its statically typed like Java and Scala, although there are some dynamic features.
I've been meaning to blog about it for some time, but Cedric beat me to it (and its a good writeup too).
Basically, Fantom fixes 95% of the pain points in Java in a manner and style that is close to that which you'd naturally pick if you were creating JavaNG/Java3/BetterJava. Here is a quick rundown of the key features and changes:
The basic unit of grouping code is the Pod. This is like a combination of a Java package and module. It forms a key part of the name of any type in the same way as the package name does. But because it is also the module, it is easy to find missing classes - its like every class file knowing what jar file it is stored in. There is also a module level access specifier ('internal'), which is a cross between package scope and proposed 'module' scope in Java.
The two main types of type are classes and mixins. Classes are as expected, with single inheritance. Mixins are like interfaces, but can have implementation too, providing convenient and safe multiple inheritance if required.
Slots are the contents of classes and mixins. There are only two types of slot - fields and methods. All fields behave as properties, and are accessed via methods. You don't need to manually write the getter/setter, but you can if you need to, such as with calculated fields. Methods are pretty much as expected, except that you have to declare them as virtual in order to allow them to be overridden (and you have to declare override if you are overriding).
One key point is that all slots have unique names. This means that a field cannot have the same name as a method. This is a Good Thing, and allows method/field references to just reference the slot name (contrast this with the FCM method reference spec).
It also means that methods cannot be overloaded! But this is also a Good Thing, when combined with default values for method parameters, for example either of the last two arguments may be omitted and will default to zero:
Date withDate(Int hour, Int minute, Int second := 0, Int milli := 0) {
....
}
The totality is a very simple, but consistent, basic structure.
Constructors are defined like static methods, but use the method name 'make' by convention. This method name and design is designed to allow easy switching from creation of objects to returning cached objects (or specialised subclasses) without affecting the caller:
class Date {
new make(Int hour, Int minute, Int second := 0, Int milli := 0) {
....
}
}
The 'new' keyword indicates that the method is a constructor.
All assignments use the := symbol. This clearly separates them from any other usages of =. It also enables a basic form of type inference when declaring local variables:
value := 6 str := "Hello world"
Note that there was no need to declare the variable type (Str/Int). Declarations of fields still require the type to be specified though.
Fantom also supports operator overloading by delegation to methods. Thus, writing a method with a special name will cause the matching operator to be allowed.
As a result, there is no need to call a.equals(b). The == operator is mapped to the equals method - this one change makes code a lot neater.
Immutability (using the 'const' keyword, although a different meaning to C) is built into the language. Fields and classes can be immutable, as these gain extra power in the language.
The main benefit is with multi-threading. The language prevents there being any shared mutable state between two threads. Only immmutable objects may be freely passed between threads. If you need to pass a mutable object to another thread, then it must be serializable (using the built in serialization) and it will be sent to the new thread as a serialized message There is thus no synchronized keyword.
Collections and Closures are the only places where anything like generics appears. The collection classes have dedicated type signatures, which look like Java array signatures:
String[] listOfStrings := ["one", "two", "three"] String:Int[] mapOfStringsToInts := ["one": 1, "two": 2, "three" : 3]
Note that both the list and map also have a literal syntax to define initial contents.
Closures are built in, and the API is written to work with them. The syntax is modelled after Ruby, but is pretty readable to a Java developer, using pipes to define the closure arguments:
list := ["one", "two", "three"]
list.each |Str val, Int index| {
echo("$index = $val")
}
Note how local variables can be accessed and output from within a string (like Groovy amongst others).
Fantom encourages more dynamic coding styles. If you use the dot to call a method (as per normal Java) then the method is compile time checked. If you use the arrow operator, then the method is called by reflection. Further, if the method called by reflection doesn't exist, then this error can be caught (the 'trap' method) which is like the 'method missing' concepts in other languages and enables powerful DSLs to be written.
obj.doStuff() // compile-time checked call, as per Java obj->doStuff() // runtime reflection call
This can also be thought of as enabling duck typing.
Fantom has its own API. It does not directly expose the Java API, although you can access it via the 'native' keyword. The benefit if this is the removal of all the bad and broken parts of the Java API.
The Fantom authors philosophy is to provide all the useful features of the Java API, but in less classes. Thus, the IO API consists of just 4 key classes, with byte/char operations on the same class, and buffering assumed.
Lines do not need a semicolon at the end. A newline will suffice.
There is built in serialization to a JSON like syntax. This is actually a subset of the language, and can be used to initialise objects at creation time in normal code.
Methods may have convariant returns like Java. But they can also have Self type returns.
Methods can be declared to run 'once', and then cache their value.
If, while, and basic for loops are the same as in Java. Switch statements are better, as they can't fall-through.
Exception handling is as per Java, with try, catch and finally. All exceptions are unchecked (yay!)
The default type for numbers with a decimal point is a BigDecimal equivalent, not a double equivalent. This will mean a lot fewer numerical errors.
Fantom runs on the JVM and the .NET runtime. It manages this by writing to a temporary intermediate format, which then gets further compiled to the right bytecode.
The website is really good and detailed.
Fantom is not Java, it is its own language. Yet, it is many, many ways the natural result of applying all the changes that the blogosphere asks for in Java. Just for that reason it pays to evaluate it closely.
Is Fantom a good language? The answer is a qualified yes. At the moment, it looks like a very well designed language I have very few points of contention with it - the main one being there is no non-null support. Minor points include some choices for coding standards (open curly brace positioning, and when to use method parameters).
Is Fantom a new language? Not really. It is a consolodation language, which is what James Gosling claims Java was (ie. a language that doesn't invent much that is radically new. Most of the ideas have been seen elsewhere, but Fantom has a particular JavaNG feel about it.
What are my key features? Built in modules, immutability and safe threading, closures, and a really great solution to generics (ie. only support them on Lists, Maps and Closures). The local type inference, no semicolons, == for equals and interpolated string are four minor features that make a big difference too.
Fantom is worth checking out. Whether it suceeds as a language is up to many factors - it needs an IDE for example, and a lot of luck.
The key point for me is that Fantom represents much of what JavaNG/Java3/BetterJava would look like if all our ideas were adopted. And while it has many similarities to Java, there is also quite a sense of difference. Perhaps, the biggest aspect of this is that the APIs are different. But that is perhaps inevitable if you want to get any real benefit from closures and fixing generics (by simplifying them).
And that perhaps gives us the definition of where JavaNG/Java3/BetterJava ends and BeyondJava starts. If the language is based around the Java APIs, its a JavaNG/Java3/BetterJava language (eg. Groovy). If the language has its own APIs, its a BeyondJava language (eg Fan, Scala).
All opinions welcome on Fantom and the BetterJava to BeyondJava boundary!
The reality for Java is that there are many other programming languages, and many of those have features that Java developers sometimes wish they could access. But its simply impossible to add all those features. Is there a possible alternative if we think 'outside the box'?
What I'm thinking about in this blog is the possibility of embedding Groovy, Ruby, Jython or Scala code directly within Java code.
Why might that be useful?
Well each language has their own benefits, whether Scala's functional style or Groovy's GStrings. Including a small part of another language within the main code body could be useful, although obviously this would be a technique to be used with care.
And it doesn't have to stop at known languages. What about a dedicated 'SQL language'? Or a dedicated 'XML language'? These would be more than just DSLs, but actual languages with whatever syntax rules are most applicable.
So, what might a syntax look like:
public String fetchRow(int id) {
:groovy: {
println "Row id: $id!"
}
:sql: {
SELECT %text% FROM my_table WHERE row_id = %id%;
}
return text;
}
The idea is that a block of code, surrounded by curly brackets, can be identified as belonging to a different language. In this case I've used the syntax of the name of the language (which would have to be imported) surrounded by colons. Note that there is nothing specific about the syntax within the block. Bear in mind that the syntax isn't that important - its the concept that matters.
The Groovy example - just normal Groovy code - outputs the row id using an embedded string.
The SQL example is an invented 'language' where a column is read by id, and then returned to
the Java code as the variable text.
So, what about the detail? Well, the approach requires two parts.
Firstly, there needs to be a parser for each language that understands the relevant syntax. This will typically be a variation of the normal parser for a 'real' language like Scala or Ruby. For a new language like SQL or XML, it would be written from scratch. The parser also needs to be able to recognise when the block of code in that language is complete.
Secondly, the parser needs to be able to share variables with the surrounding code. As a basic principle, this can be thought of as a map, where the other language code can both read and write to the map. Of course this requires there to be a mapping between the various type systems - for Groovy this should be easy, other languages might find that more tricky.
So how hard is this to implement? Probably pretty hard. But it does open up lots of possibiilties - wheter for embedded DSLs or larger blocks of code in another language.
This is an outline of an idea to allow other languages, whether existing or new, to be easily embedded directly in existing code. Any thoughts?
Just a quick post to outline my plans for JavaOne.
I'll be in San Francisco from Sunday, so I expect I'll be picking up my pass then. I expect the rest of the day will be more touristy, unless I get grabbed for a techie discussion!
On Monday, I've arranged a JSR-310 dates/times Expert Group session. As always though, I'm trying not to limit this to just EG members, so if you want to contribute, see the mail on the mailing list.
I'll be kept busy by the JCP during the week too. There is some JCP training on the Monday, plus, for some strange reason, I've been nominated for an award - "JCP participant of the year". Most unexpected!
Finally, of course, I'm giving a JSR-310 technical session with Michael on Thursday at 13:30, with a repeat on Friday at 13:30. The id is TS-6578.
Hope to see some of you there - and if you'd like to meetup and chat about JSR-310, Joda-Time, FCM or any of my blog posts then drop me a line at scolebourne-joda-org.
I've gathered together a few more thoughts on improving the enhanced for-each loops. The basic idea is to take this very popular Java 5 feature and provide the missing parts.
One of the more frustrating parts of the Java 5 for-each loop is when you are 80% through writing a loop, and you discover you need to remove an item, or require the loop index. At that point, you have to go back and manually change the loop to one of the old formats (in Eclipse at least). This is a hassle.
Perhaps more importantly is that the older for loops simply aren't as clear in their intentions, aren't very DRY, and are definitely more error-prone. As a result, I've documented my proposal to improve the for-each loop with control access. For example, to access the loop index:
Collection<String> coll = new ArrayList<String>();
for (String str : coll : it) {
System.out.println("Item: " + str + ", Index: " + it.index());
}
And here is an example of removing an item:
List<String> list = new ArrayList<String>();
for (String str : list : it) {
if (str == null || it.isFirst()) {
it.remove();
}
}
As can be seen, the syntax simply involves adding another colon and a 'variable' name. The 'variable' can be used access loop control and manipulation functions. Note that the additional colon and 'variable' are of course optional for full backwards compatibility.
The document discusses two strategies for implementing the syntax - either via real Java types or as a language level feature. Please read the document for more information.
I have updated my previous document about extending for-each to maps. The download of the javac implementation remains available from Kijaro.
It seems increasingly unlikely that there is time for closures to make it into Java 7. There are also many developers expressing real doubts as to whether the complexity of control invocation is just too much for the venerable Java language.
The alternative is smaller improvements like these two. They provide an easy to grasp extension to the popular Java 5 for-each loop, that might still be possible to deliver in Java 7. Opinions welcome, as always.
Have you ever been fustrated by the new Java 5 for each loop because it didn't operate directly on maps?
I have documented a proposal to change Java to allow for each loops on maps. I have also used the Kijaro project to implement the enhanced for-each loops!
Map<String, Integer> map = new HashMap<String, Integer>();
for (String str, Integer val : map) {
System.out.println("Entry" + str + "=" + val);
}
The altered version of javac can be downloaded, with the normal caveats of 'no warranty' and 'not intended for production'.
The real question here is whether we should use closures to obtain this functionality, or just code a specific language feature. Since it is far from certain that closures will appear in Java 7 due to timescale and resourcing questions, maybe we should be considering the alternatives?
Extending for-each loops to cover maps is a simple extension to the Java language that introduces no radically new concepts. Existing developers should be able to pick up the feature without any difficulty. In addition, developers that have never been exposed to the feature (but have seen a Java 5 for-each loop) should be able to read the code and grasp the meaning without tuition.
The truth is that sometimes the simple solution is the right one. Perhaps, closures are overkill for many of the uses in Java? Hopefully this document and prototype will allow people to kick the tyres on implementing this concept as a language feature allowing a fair comparison with closures.
I've released a document and prototype of For-each loop for Maps, a language change to build on the Java 5 for-each loop. All feedback welcomed!