With an emphasis on functional style and a couple of lumps of syntactic sugar, Xtend hopes to retain all of Java’s strengths and none of its weaknesses.
Java is the most successful language on the planet. There are close to 10 million developers writing all kinds of software systems in it; the best IDEs on the planet are Java IDEs; and the vast amount of exciting open-source frameworks, libraries, and tools are very good reasons to use it. Also, a lot of the concepts in Java are well thought out. Even more importantly, they are mature and well understood.
Java is also known to be a very inflexible and ceremonial language, forcing the developer to repeat redundant information over and over again. In fact, this is why Java IDEs have to be so powerful: to help us to write all that boilerplate!
But as we all know, code is read much more often than it is written. So this aspect of Java is a real problem. We could try to fix it with IDEs, but that’s just throwing yet another load of tools on the pile. We should fix the problem where it’s caused: we need a better Java.
Java + Xtend == Better Java
Xtend is a statically-typed programming language developed at Eclipse.org. It has a strong focus on leveraging all the good parts of Java, including seamless integration with the huge amount of Java frameworks and libraries out there. Experienced Java developers can get started with Xtend in almost no time, since everything is so familiar. The editor integrates tightly with Eclipse’s Java tooling to ensure a seamless integration in the IDE as well. If you know how the Java tools work, you will feel at home with Xtend’s UI.
The good parts of Java make for a great basis, but Xtend is all about extending that. For instance, you can now simply discard all that boilerplate you are used to generating using your IDE. Reasonable defaults, type inference, and some other powerful features can make code surprisingly readable. Closures and operator overloading are fun things to have as well. With Xtend you can use such beyond-Java features without learning a whole new language.
Xtend is not meant to be a replacement for Java but serves more as an add-on. When working with Xtend you still write the interfaces, enums, and annotations in Java. There’s little value in changing the syntax of these concepts, as they are already very compact, well-known, and tooling-wise nicely supported. The added value with Xtend is the very concise way to implement Java classes. And if you feel like shifting some bits around, you can always go back to Java. The two languages integrate seamlessly in both directions.
So let’s write some Xtend code. The ubiquitous “Hello World” program would look like this:
At a first glance, the most obvious difference from Java is the def keyword, which is used for method declarations. Other than that you might notice that there are no mandatory semicolons and no explicit visibility modifier. In Xtend every class and method is public by default. Fields, on the other hand, are private if you don’t specify the visibility differently. Xtend supports private, protected, and public visibility, sharing the exact same semantics you know from Java. Java’s default visibility (package-private) is not supported.
The println function is automatically imported, similar to members of the package java.lang. The method is defined in a thin runtime library that is part of Xtend. It contains only a dozen classes, adding some convenient functionality on top of the Java SDK.
Getting Rid of the Boilerplate
Let’s make it more interesting by looking at a more realistic example. Let’s say we have a method that should turn a list of strings into their uppercase versions. This is the noisiest version you could write in Xtend:
Besides the def and the val keyword it looks like the Java code most people would write. Let’s now make it a bit more concise by applying type inference and other sugar:
This is already a bit better. We removed the majority of explicit type information, since the compiler doesn’t need it to understand the code. You can have it if you think it improves readability, but in Xtend you are not forced to write it down.
Many people claim that Java generics are bad because they force you to specify the type arguments on the client side. Type Inference reduces this problem dramatically, as you can see.
You might also have noticed that we’ve replaced the invocation of List.add(T) with the operator +=. In Xtend, operators are just an alternative syntax for method invocations, hence you can easily use any operators on any type if you want to. The += operator for java.util.Collection is defined in the runtime library mentioned earlier. This feature not only allows you to have nice arithmetic operators on numeric types like java.math.BigDecimal, it also comes in handy in many other scenarios. In Xtend you can, for example, create an instance of a HashMap like this :
In fact, the -> operator is an extension method defined like this:
But let’s get back to the previous example, where we turned strings into their uppercase versions. Although the applied sugar has improved the readability of the code a lot, the code is still very imperative, which is hard to grasp and error-prone.
Enter Functional Programming
Functional programming advocates a stateless, side-effect-free programming style, avoiding all kinds of imperative programming based on state changes. In strict functional programming, statements don’t exist, but everything is expressed in terms of pure functions that evaluate to the same result if invoked with the same arguments. There’s ultimately no global state or anything like that.
Being a Java-like language, Xtend doesn’t go that far but it goes pretty far. For instance, it doesn’t have statements. Everything that looks like a statement is actually an expression. Even a block is just an expression. Now you can use things that look like statements in places where it’s just not allowed in Java. Here’s an example:
In Java it wouldn’t be possible to use a try-catch on the right-hand side of an assignment. Since it’s a statement it doesn’t result in a value. In Xtend, however, everything is an expression and the result would be either the result of fileContentsToString or the string “dummy data” in case an IOException was thrown. By the way: Xtend doesn’t force you to catch checked exceptions. They are just rethrown in such a way that the compiler doesn’t complain, using a technique introduced by Lombok.
Another important ingredient of functional programming is higher-order functions. These are functions that get other functions passed in as an argument. We already have functions like this in Java. For instance java.util.Collections#sort(List, Comparator) is effectively a higher-order function since a Comparator usually is really just a function able to compare two instances of the same type. However, in Java there’s no concise syntax to implement an instance of Comparator. The most concise way would be an anonymous class.
Xtend, on the other hand, allows you to use function literals instead of anonymous inner classes. Those function literals are way more readable and can be passed to higher-order functions. They adapt transparently to the type that the invoked function expects. Xtend uses a syntax similar to the one known from Smalltalk and adds a couple of very useful higher-order functions to Java’s collection library by means of extension methods. This allows you to transform the list of strings from the previous example like this:
The functional style is not only much more readable but also less error-prone. Also note that in Xtend, as in most other modern languages, a return is implicit. The last expression in a block is automatically returned if the method’s return type is not void.
In case you were wondering how java.util.List got this new fancy map method, it’s defined in the class ListExtensions, which is implicitly imported as an extension method. It’s part of Xtend’s runtime library and ultimately delegates to the collection library of Google Guava. If you want to use your own extension methods or want to use some existing methods as extension methods, you can import them using the extension keyword. Let’s have a look at an example:
Both calls to sort will invoke a static member of java.util.Collections. The second example also shows how closures are automatically converted to existing Java types. In this case the closure is translated to an anonymous class of Comparator.
Extension methods are even more interesting in chained expressions, because they effectively allow you to write and read from left to right. That’s much more natural than reading inside out as you need to do when using the typical functional infix syntax. Imagine the following nested invocation of methods:
You need to read this inside out if you want to follow how it is executed. Using extension method syntax, you can write it like this:
Unlike other languages, Xtend doesn’t force extension methods to be static. Any locally declared method can be used as an extension and it’s even possible to use methods from local fields as extension methods. This is especially useful if you use dependency injection, as we will see later. But how can you define polymorphic extension methods for a whole type hierarchy?
Multi Methods (aka Dynamic Dispatch)
Let’s say you have a type hierarchy of shapes, Shape being the abstract super type of Circle and Rectangle, which are the two initial concrete cases. There are all kinds of computations you might want to do with shapes in the future, and we don’t want to modify and recompile the shape hierarchy every time we add some new functionality or add a new concrete subclass.
This problem is commonly known as the expression problem, which Xtend solves in a very elegant way.
New functionality is defined using extension methods. For instance, computing the area of a shape could be implemented like this:
Using extension methods we are now able to compute the areas of circles and rectangles:
But of course we want to be able to call area on any element of type Shape and of course it should behave in a polymorphic way: The actual method to call will be picked at runtime using the runtime type of the shape. To do that you would add the dispatch keyword to the set of overloaded methods:
Now the compiler will infer one synthetic entry method, using the most common method signature. In this case that would be the signature def int getArea(Shape shape) since the common super type of Circle and Rectangle is Shape. The implementation of that method dispatches every call to the right case based on the runtime type information. It always finds the best match.
This is how you would use the extension methods in your code:
As you can see we didn’t use static extensions here, but have the extension method injected. We typically prefer Google Guice, but any dependency injection container should do and you could of course also use old-fashioned factories or the like to initialize the field.
Extension fields don’t need to have a name, since we will not directly refer to them. The expression shape.area is translated to this._shapeGeometry.area(shape).
Adding New Functionality
Let’s now assume you want to add a Triangle to the hierarchy, but you still cannot modify or recompile any code. What would you do?
In Xtend you would define the class Triangle and create a subclass of ShapeGeometry, where you add another dispatch method:
Xtend will infer a new synthetic dispatch method and override the one from the super class. Of course it will dispatch to every declared dispatch method including the ones from the super classes. Now you only need to tell your dependency injection framework to inject an instance of ShapeGeometryForTriangles if asked for an instance of ShapeGeometry.
There are other interesting language features in Xtend, like the sophisticated whitespace handling in template expressions and the cool switch expression. But one thing stands out.
Exceptional DSL Support
A domain specific language (DSL) is a small executable language solving a particular problem. Imagine you are working on a web framework. A typical task is to map http requests to controller methods or other resources. Instead of configuring that in an untyped, clumsy XML file, you could define it like this:
Wouldn’t it be cool to have all the great tool support you see in Xtend, including specific validations, which for instance would warn you about certain unreachable mappings? Also the references to classes and methods should be statically typed, including content assist, and even cross-language rename refactoring would be extremely nice. With Xtend and its support for DSLs this is an easy thing to do.
Xtend is built with Xtext, Eclipse’s language and IDE development framework. With that tool chain you can build such a request mapping language in no time. It will enable you to embed Xtend’s expressions, Java types, and annotations everywhere you want. These languages provide much more functionality and IDE support than anything you can do with internal DSLs and the definition of such a language is not rocket science. Have a look at the tutorial on Xtext’s website to understand how to do that.
While learning a completely different programming language is something every developer should do from time to time, switching a whole project and all its team members to a new language is a huge effort. Xtend lets you use all your Java knowledge and existing Java code. At the same time the lightness of its concise syntax and the encouraged functional style will make programming much more enjoyable. The tooling is pretty close to what Eclipse’s Java Development Tools can do today and in some aspects it even works a bit better. The compiler, on the other hand, is completely Eclipse-independent and can be executed in any Java process. There is even a Maven plug-in to translate Xtend code to Java source code.
If you want to try it out, you could use the Eclipse Market Place Client from within Eclipse or go to the website and download a ready-to-use Eclipse distribution. Next you could materialize a tutorial project using the wizard. But as you’ve read this far you should be able to start right away. Just use the file wizard in the Java perspective to add an Xtend file to any of your Java projects. Unit tests are often a good starting point. ;-)
Sven Efftinge is the lead designer of Eclipse’s Xtend and Xtext. He lives and works in Kiel, Germany and runs an open-source development lab for itemis, a company specialized on Eclipse-based tooling and domain-specific languages.