Showing posts with label xtend. Show all posts
Showing posts with label xtend. Show all posts

Wednesday, September 04, 2013

Better I18n in Java

Internationalization is not the most loved topic for Java developers. This is merely because it makes code less readable and introduces the need to work with property files and constants. As a result there is no static typing in that area and we are in need to get supported by tools, such as IDEs. In this blog post I want to show how this can be elegantly solved with Xtend.

I18n - The JDK Way

The JDK offers well working facilities for externalizing messages and formatting values such as dates and currencies in a proper localized way. For externalizing messages the class ResourceBundle is your friend, as it not only reads and parses property files but also supports flexible way of how property values are looked up based on Locales. The other interesting bit is the MessageFormat hierarchy which contains strategies to turn data types into localized strings.

The provided functionality is very powerful but enforces a cumbersome programming model. The standard way is to have a bunch of property files and whenever you need to get the contained values you use a ResourceBundle which has to be created like this:

ResourceBundle messages = ResourceBundle.getBundle("MyMessages", localeToUse);

Now you obtain the messages using the property keys, which are just strings. To minimize very likely spelling problems and it is good practice to have a declaring all the keys as constants. Then you only have to declare them once in the code and once for each property file.

public class MyMessagesKeys {
  public final static GREETING = "greeting";
  ...
}

Clients can access the values using the constants :

messages.getString(MyMessagesKeys.MY_KEY);

A common requirement and feature is to have variables in the messages which should provided by the program. These arguments can even be of different types, where the MessageFormat types come in. But again the Java compiler doesn't know if there are any arguments, nor how many and of which types they are. So you are back in untyped land and will learn about your errors only at runtime.

Let's see how we can improve the API for the JDK classes, such that we get rid of all the duplication and weakly typed access.

DRY With Xtend

Xtend is not a language which is meant to be used instead of Java, but is an extension to Java. You should use it in places where Java just doesn't cut it, like in this example.

In the following we're going to built a statically typed API to be used from Java by means of an active annotation. The basic idea is, that we make the compiler turn a constant containing a message into a Java facade and a corresponding properties file. Consider the following declaration of messages:

@Externalized class MyMessages {
  val GREETING = "Hello {0}!"
  val DATE_AND_LOCATION = "Today is {0,date} and you are in {1}"
}

This is all the developer should need to declare. Now we implement an active annotation, that turns the field declarations into static methods. It even adds typed arguments for the placeholders in the messages. That is the generated Java provides the following sigatures:

// Generated Java signatures

/**
 * Hello {0}!
 */
public static String GREETING(String arg0) { ... }

/**
 * Today is {0,date} and you are in {1}
 */
public static String DATE_AND_LOCATION(Date arg0, String arg1) { ... }

The actual values are written to a *.properties file and the implementation of the static methods use a ResourceBundler to look them up. So in case you need a locale-specific translation, you only need to add an additional *.properties file. Even that could be easily validated for miss-spelled or non declared keys. But I'll leave this feature as an exercise for other people :-).

Java clients can now access the messages in a statically typed way, and if you are working within Eclipse you even get the default message displayed when hovering over a property.

Building The @Externalized Annotation

Developing the active annotation is relatively easy. First you need to create a separate Java project. Although an active annotation is just library, it has to sit in an upstream project or jar, i.e. cannot be used within the same project. We would run into chicken 'n egg problems during compilation if that was allowed.

In that project create a new Xtend file and name it Externalized.xtend. We first declare the annotation and annotate it with @Active so the compiler is aware of it being an active annotation. We also have to provide a processor class which is executed by the compiler:

@Active(ExternalizedProcessor) annotation Externalized {}

class ExternalizedProcessor extends AbstractClassProcessor {

  override doTransform(MutableClassDeclaration clazz, extension TransformationContext ctx) {
    // To be implemented ...
  }

  override doGenerateCode(ClassDeclaration clazz, extension CodeGenerationContext ctx) {
    // To be implemented ...
  }

}

As you can see two callback methods have been overridden, which correspond to certain phases in the compiler. The first phase we participate in is doTransform in which the annotated classes can be mutated. The second phase doGenerateCode allows us to write to the file system. We will later write the properties files during this phase. The doGenerateCode phase has been introduced in version 2.4.3, so make sure you have updated accordingly if you want to use this.

Step 1: Transforming The Fields Into Methods

We want to turn all field declarations into static methods, so we first iterate over the declared fields of the given class.

override doTransform(MutableClassDeclaration clazz, extension TransformationContext ctx) {

  for (field : clazz.declaredFields) {

    // get the actual value of the field
    val initializer = field.initializerAsString

    // create a message format object for that value
    val msgFormat = try {
      new MessageFormat(initializer)
    } catch(IllegalArgumentException e) {
      field.initializer.addError("invalid format : " + e.message)
      new MessageFormat("")
    }

    // check the syntax and report back in case of problems
    val formats = msgFormat.formatsByArgumentIndex
    if(msgFormat.formats.length != formats.length) {
      field.initializer.addWarning('Unused placeholders. They should start at index 0.')
    }

    // add a method using the field's name
    clazz.addMethod(field.simpleName) [

      // return type is always string and the method is static
      returnType = string
      static = true

      // add parameters for the given arguments in the message format object
      formats.forEach [ format, idx |
        addParameter("arg" + idx,
          switch format {
            NumberFormat: primitiveInt
            DateFormat: Date.newTypeReference()
            default: string
          })
      ]
      
      // add the value as a comment, for documentation purpose
      docComment = initializer
      
      // add the actual body. It's generated Java code.
      val params = parameters
      body = [
        '''
          try {
            String msg = RESOURCE_BUNDLE.getString("«field.simpleName»");
            «IF formats.length > 0»
              msg = «toJavaCode(MessageFormat.newTypeReference)»
                    .format(msg,«params.map[simpleName].join(",")»);
            «ENDIF»
            return msg;
          } catch («toJavaCode(MissingResourceException.newTypeReference)» e) {
            // TODO error logging
            return "«initializer»";
          }
        ''']
    ]
  }

  // now that we have the methods we can just remove the fields, 
  // as they are no longer needed
  clazz.declaredFields.forEach[remove]

  // add a static ResourceBundle to be used from the methods we just created.
  clazz.addField("RESOURCE_BUNDLE") [
    static = true
    final = true
    type = ResourceBundle.newTypeReference
    initializer = ['''ResourceBundle.getBundle("«clazz.qualifiedName»")''']
  ]
}

Now we have successfully transformed an @Externalized class written in Xtend into a Java class containing corresponding static methods.

Step 2: Generating The Properties File

The last thing we need to do now is to write the values of the fields into the properties file. For this we participate in the code generation phase by overriding doGenerateCode. While during doTransform we got a mutable Java representation of the original sources, in this phase we get the unmodifiable original source passed in.

override doGenerateCode(ClassDeclaration clazz, extension CodeGenerationContext ctx) {
    
  // obtain the target folder for the given compilation unit
  val targetFolder = clazz.compilationUnit.filePath.targetFolder
    
  // compute the path for the properties file
  val file = targetFolder.append(clazz.qualifiedName.replace('.', '/') + ".properties")

  // write the contents to the file
  file.contents = '''
    «FOR field : clazz.declaredFields»
      «field.simpleName» = «field.initializerAsString»
    «ENDFOR»
  '''
}

Check Out The New Release

The described example is included in the "active annotations examples" coming with latest release.

Monday, December 17, 2012

Java 8 vs. Xtend

As you might know Java 8 will finally bring an important new feature to the Java programming language :
Lambda Expressions, a feature already supported by many other languages, such as Xtend

Xtend is a statically typed JVM language that translates to readable Java source code. It's very different to other JVM languages in the sense that aims to be a better Java by better supporting existing Java idioms and fully supporting the existing ecoystem. Xtend doesn't force you to rewrite your existing Java apps or drop your beloved and well-proven frameworks, but instead allows for using existing Java APIs in a much nicer way without any interoperability issues. In contrast to e.g. Scala or Clojure it is more like an extension to Java than a replacement.

Identifying and supporting existing Java idioms is not too hard given the huge existing code base but what about the future? Will Xtend also be a better match for the upcoming Java 8 libraries which were explicitly defined for the new Java 8 lambda syntax?

To find out I simply looked at Brian Goetz’s latest version of State of the Lambda : Libraries Edition and translated the contained Java code examples to Xtend.

In the following you see the code for Java as written by Brian and the translation to Xtend. Both are using the exact same Java 8 APIs and contain the same amount of static type information!

Example 1

Java 8:
shapes.forEach(s -> { s.setColor(RED); });
Xtend:
shapes.forEach[color = RED]

This first example already reveals most of the important differences.

First the general syntax for a lambda expression in Java is using an arrow (->), while Xtend uses squared brackets (like smalltalk). Also in Xtend a lambda expression doesn't need to be passed using braces. Although you could write shapes.forEach([color = RED]) you don't need to.

In Java 8 the body of a lambda is either a block or a single expression. So whenever you need to use a statement you have to add the curly braces and semicolons. In Xtend everything is an expression and the lambda itself is already a block expression.

In Xtend you can omit the declaration of a parameter name. In that case the parameter is called 'it' and is implicit (similarly to 'this'). If you want to give it a name you do it like this : shapes.forEach[ s| s.color = RED]

Unrelated to Lambdas but interesting in this case: Xtend allows to use assignments to call setter methods.

Example 2

Java 8:
shapes.stream()
      .filter(s -> s.getColor() == BLUE)
      .forEach(s -> { s.setColor(RED); });
Xtend:
shapes.stream
      .filter[color == BLUE]
      .forEach[color = RED]

Not too much new stuff in here. Xtend lets you omit empty parenthesis and you can call a getter using the property's name.

Example 3

Java 8:
List<Shape> blue = 
    shapes.stream()
          .filter(s -> s.getColor() == BLUE)
          .into(new ArrayList<>());
Xtend:
val blue = 
    shapes.stream
          .filter[color == BLUE]
          .into(new ArrayList)

Here we see type inference in action. While you can use the diamond operator in Java, you can leave it out in Xtend. Also the variable doesn't need to be explicitly typed as the type can be fully inferred from the right hand side.

Example 4

Java 8:
Set<Box> hasBlueShape = 
    shapes.stream()
          .filter(s -> s.getColor() == BLUE)
          .map(s -> s.getContainingBox())
          .into(new HashSet<>());
Xtend:
val hasBlueShape = 
    shapes.stream
          .filter[color == BLUE]
          .map[containingBox]
          .into(new HashSet)

Note how readable the lambdas get when you can leave out all the cryptic clutter. Let's compare a last example from a later section of the document:

Example 5

Java 8:
List<Album> sortedFavs =
    albums.stream()
          .filter(a -> a.tracks.anyMatch(t -> (t.rating >= 4)))
          .sorted(comparing(a -> a.name))
          .into(new ArrayList<>());
Xtend:
val sortedFavs =
    albums.stream
          .filter[tracks.anyMatch[rating >= 4]]
          .sorted(comparing[name])
          .into(new ArrayList)

Although the libraries as well as the examples have been written for Java 8, the Xtend code is still much less cluttered with symbols and therefore significantly more readable. Yet the type information is exactly the same! Xtend is just a bit smarter with type inference and is syntactically less rigid.

Besides that and the fact the Xtend compiles to readable Java 5 code, it has many other important features to offer.

Thursday, November 15, 2012

Active Annotations Explained - JavaFX Properties

Today I'd like to give a more detailed example of how active annotations can be used to solve real world problems. Active annotations are an upcoming language feature for Eclipse Xtend, which allow you to participate in the translation step from Xtend code to Java using annotations.

JavaFX Properties

JavaFX comes with a very nice binding and properties framework, which allows for easy connection of model properties and widgets. It even has support for expressions, like String concatenations, which are reevaluated automatically, when a property changes.

I have used it in a login screen, such that the welcome message get's updated when you type in the user name.

Unfortunately defining JavaFX beans is not so nice, as it requires a lot of boilerplate. Michael Heinrichs, technical lead of JavaFX Properties, recommends the following pattern in his blog:

// Java boilerplate
public class Login {

  private String userName = "";

  private SimpleStringProperty userNameProperty;

  public String getUserName() {
    return (this.userNameProperty != null)? this.userNameProperty.get() : this.userName;
  }

  public void setUserName(final String userName) {
    if (userNameProperty != null) {
      this.userNameProperty.set(userName);
    } else {
      this.userName = userName;
    }
  }

  public SimpleStringProperty userNameProperty() {
    if (this.userNameProperty == null) { 
      this.userNameProperty = new SimpleStringProperty(this, "userName", this.userName);
    }
    return this.userNameProperty;
  }

  // ... same pattern for the password goes here

}
  
That's a lot of code. Given that we usually have to map a lot of properties to the UI, you don't want to write and maintain that.

Code generation to the rescue?

The typical solution in those scenarios is to come up with a little DSL and a code generator. In Java land we really know how to do that and there is easy to use technology available to build ... yet another entity DSL. And it's definitely a much better approach than maintaining above's code by hand, but ...

The big advantage of frameworks such as Xtext is the flexibility they provide. You can build all kind of tooling and choose the right syntax for the problem. No compromises. However, there are certain classes of DSLs which really don't need or use the syntactic flexibility since they are close to class-like structures : Entities, Services, etc.

In addition building an external DSL introduces a bit of an extra complexity in the development turnarounds: You'll have to maintain an Eclipse Plug-In and deploy it synchronously with the rest of your framework to all developers in your team. And just like everything else in your project, the DSL and the code generation evolve over time. So you have to keep everything in sync and deploy and install new Eclipse plug-ins every time your DSL enhances.

Don't get me wrong there are many situations where the additional flexibility of Xtext is extremely useful, but for a certain class of DSLs you are better off with active annotations.

JavaFX Beans with Active Annotations

So let's see how we can replace JavaFX beans like the one shown above with a more readable and maintainable variant.

First we replace the Java class with the following Xtend class:

@FXBean class Login {
  String userName
  String password
}

Next we define the referenced annotation, like so:

@FXBean for class {

  process each {
    inDerivedJavaClass(it) [
      for (f : declaredFields.toSet) {
        //TODO create property field
        //TODO create getter
        //TODO create setter
        //TODO create property accessor
      }
    ]
  }
}

The syntax is a bit different from Java's since we are convinced that reusing the keyword interface for an annotation, as Java does, is surprising at least. Also the annotation target (class in this case) is a first class syntax construct and is not encoded in another annotation.

The important part is the 'process'-hook, which will be called by the Xtend compiler, for every class that is annotated with @FXBean. Therein we state that we want to iterate over the declaredFields in the context of the derived Java class.

In the following we are going to replace the individual TODOs to make the compiler create a real JavaFX property from just a single field declaration.

We start by declaring a couple of local variables we'll use in the following:

process each {
  inDerivedJavaClass(it) [
    for (f : declaredFields.toSet) {
      val fieldName = f.simpleName
      val fieldType = f.type
      val propName = f.simpleName+'Property'
      val propType = f.type.toPropertyType(this)

  ]
}

The extension method toPropertyType() is not shown here, but it's really just a small utility method I built, which will return the JavaFX property type for the field's type. E.g. when asked with the type String the extension method returns the type SimpleStringProperty. Such utility methods simply reside on the classpath just like the annotation itself.

Let's now create the field.

process each {
  inDerivedJavaClass(it) [
    for (f : declaredFields.toSet) {
      val fieldName = f.simpleName
      val fieldType = f.type
      val propName = f.simpleName+'Property'
      val propType = f.type.toPropertyType(this)
      
      // create a field for the JavaFX property type
      field(propName, propType)
    }
  ]
}

The method field(String, Type) adds a field to the class in context using the given name and type. We could also change existing Java information here, like visibility and so on and also have an initializer or add annotations. You can even create new Java classes interfaces, etc.. Basically everything you can do in Java, can be done here.

Next up we create a 'getter'-method:

process each {
  inDerivedJavaClass(it) [
    for (f : declaredFields.toSet) {
      val fieldName = f.simpleName
      val fieldType = f.type
      val propName = f.simpleName+'Property'
      val propType = f.type.toPropertyType(this)
      
      // create a field for the JavaFX property type
      field(propName, propType)
      
      // getter
      method ('get'+fieldName.toFirstUpper, fieldType) [
        body = 
          'return (this.'+propName+' != null)? 
               this.'+ propName +'.get() : this.'+fieldName+';'
      ]
    }
  ]
}

Nothing special here. The square brackets are a lambda expression wherein you can customize the created method. We assign a body in this case.

The other two methods are created similarly:

@FXBean for class {
  
  process each {
    inDerivedJavaClass(it) [
      for (f : declaredFields.toSet) {
        val fieldName = f.simpleName
        val fieldType = f.type
        val propName = f.simpleName+'Property'
        val propType = f.type.toPropertyType(this)
        
        field(propName, propType)
        
        // getter
        method ('get'+fieldName.toFirstUpper, fieldType) [
          body = 
            'return (this.'+propName+' != null)?
                 this.'+ propName +'.get() : this.'+fieldName+';'
        ]
        
        // setter
        method ('set'+fieldName.toFirstUpper, type('void')) [
          param(fieldName, fieldType)
          body = 
            'if ('+propName+' != null) {
               this.'+propName+'.set('+fieldName+');
             } else {
               this.'+fieldName+' = '+fieldName+';
             }'
        ]
        
        // property accessor
        method (fieldName+'Property', propType) [
          body = 
            'if (this.'+propName+' == null) { 
               this.'+propName+' = 
                 new '+propType.identifier+'(this,"'+fieldName+'",this.'+fieldName+');
             }
             return this.'+propName+';'
        ]
      }
    ]
  }
}

And that's it. What you can't see here, is that everything gets updated and recompiled instantaneously on safe. Also important to note, is that you don't need any additional compiler configuration. Just have your active annotation on the classpath (e.g. distributed via jar or in the some project) is enough to use it and have the compiler applying it. And this of course works wherever you compile Xtend code (Command Line, Eclipse, Ant, Maven, etc.).

Naturally the IDE and the compiler is aware of what you do in the processing so, you'll for instance get the expected content assist proposals, ca use the typical navigation features and see the synthetically derived methods and fields in the outline view.

The following screen cast shows everything in action:

Tuesday, October 23, 2012

Introducing : Active Annotations

In this article I'd like to introduce you to a new important language feature for Xtend. Xtend is a statically-typed language which compiles down to readable Java source code.

Active Annotations in a Nutshell

Active Annotations allow for participating during the translation of Xtend code to Java source code. You basically declare an annotation and with it provide the processing instructions where you can
  • issue errors and warnings,
  • provide corresponding quickfixes,
  • apply all kind of changes and enhancements to the target Java classes,
  • introduce new Java types or
  • even update or create ordinary text files (e.g. web.xml).

To use such an annotation you just have to have it on your class path like any ordinary Java annotation.
You could for instance want to have an annotation called @Entity, which turns simple classes with fields into data classes tailored for your project-specific context. You'd define and maintain the definition of what an entity is right in your project and would version and distribute it just like any other API. The IDE will be fully aware of the processing changes. Not only will errors, warnings and quickfixes be available in the IDE but also the scopes, type computation and content assistance will behave according to your processing instructions.

General Use Cases

Let's have a look at some use cases. Xtend already comes with two annotations, whose processing for now is hard coded into the compiler. We did so, to gain some experience with the general idea and will of course replace the hard coded version with 100% library-based annotations in a future release.
One of these annotations is the @Property annotation, which translates a simple field into a Java-Bean property. That is given the following Xtend code
   // Xtend
   @Property String name
you'll get this Java code :
   // Java
   private String name;
   public String getName() {
      return this.name;
   }
   public void setName(String name) {
      this.name = name;
   }
The other annotation Xtend already has is @Data which translates a class with fields into a value object รก la domain-driven design, i.e. it creates an immutable class with a value-based equals and hashcode implementation and a nice toString implementation. We will likely support other generic use cases such as @Delegate, which generated delegate methods for an annotated field and @Builder which will automatically derive a builder API for a set of classes.

Framework-specific Use Cases

You might have seen pre-built annotations which do participate in the compilation project with other technologies. The real coolness about active annotations in Xtend is that everybody can develop their own project specific ones easily. If you want to change the behavior, just navigate to the annotation and do your changes. You will instantly see the result, since every referencing Xtend file will be re compiled on change. And it is fully transparent since everything is translated to readable Java source code!
With this simplicity to develop and deploy them people will be able to use them to remove tedious structural boilerplate in many Java APIs. We for instance built two active annotations for GWT. One for remote services, which automatically derives the required interfaces and adds the required super class. Another which automatically adds fields declared in a UI-Binder XML file. You can find some slides here and the source code is on github.

Outlook

Today we have a working prototype, which you can play around with if you are brave enough. But there's no documentation and the API changes on a daily bases, so better wait a bit. We will release a beta version of this new feature with the next release (planned for December/January), but this will still lack some important features and the API will be subject to change.

I am very excited and think active annotations really solve a huge class of problems in a very nice way and am really curious with what kind of annotations people will come up in the future.

Alan Kay once said about Lisp that it is not a language but a building material. Active annotations bring the power of Lisp Macros to the statically typed Java world.

Monday, October 01, 2012

Current Development and Future Plans for Xtext and Xtend

It has been a couple of weeks now since we released Xtext and Xtend with Eclipse Juno. Time for an update on what we are doing and where we want to go. In the following I describe the main new topics the team is working on. In addition to what is described below there is of course also a lot of maintenance work we are doing, i.e. fixing bugs and improving the core framework. Also we are doing some awesome work for customers, which I’m not allowed to talk about (But, yes, you can hire us. Even the whole team!).

Editors For Other Platforms

We are experimenting with support for other IDE-platforms than Eclipse. The first platform we are looking at right now is the web, more concrete Orion. Other platforms we want to look at are Netbeans, Xcode, Visual Studio and IntelliJ. Also basic configuration settings for TextMate and the like could be something we will be looking at.
Which one do you think is most interesting?
This part of our work is funded by Zukunftsprogramm Wirtschaft


Improved Type System

The type system and linking for Xbase-based languages (Xtend falls into this class) is currently redeveloped. Although the existing one does a decent job it has some architectural flaws which makes it too slow when working with bigger files. The new one is fast and it can do even more and cooler things. Type inference, for instance, now uses control flow analysis. That is you can write the following:
val myMap = newHashMap
myMap.put(23, new StringBuilder)
myMap.put(42, "some string")
// myMap is of type Map<Integer, CharSequence> by now
There are some other new features, which are possible with the new typesystem and even more importantly it will fix the outstanding typing bugs and be a solid foundation for future improvements. I'm sure there will be a blog post about the details in the next couple of weeks.

Formatting

Xtend gets a new formatter. I’m already using it on a daily basis and must say that it works very well. Especially with a language like Xtend which is syntactically much more flexible than Java, you need to look into language idioms to make sure a formatter does what you expect. There will also be a preference page to adjust formatting settings, but it won’t have as many options as the Java formatter in the beginning. Would be nice to have some more beta testers and feedback. What kind of options do you want to see?
Although we are implementing the formatting for Xtend now, we plan to have a new or at least an improved API for all Xtext languages. And of course the formatting for the expression goes into Xbase.

Active Annotations

Active Annotations allow you to participate in the translation step from Xtend to Java source code. It’s a bit like Java’s annotation processing but much more flexible and less complicated to integrate at the same time. You basically declare an annotation and implement a processing method, where you define how to translate annotated Xtend code to Java. I'll write a separate blog post on this.
Also Sebastian is giving a sneak-preview on Active Annotations tomorrow at JavaOne and the feature will play an important role in the session Web Development with GWT and Xtend Olli and I are giving at EclipseCon in a couple of weeks.

Release Plans

Currently the overhauled type system has highest priority and we are targeting a release as soon as it is done. We hope to have it in December this year. That release will contain the formatting and might have an @Beta-flagged prototype for Active Annotations included. We plan to have a prototype for Xtext & Orion later this year as well, maybe the team can even give a so demo during their EclipseCon talk.

Additional Topics

I want to make contributing simpler. The idea is to provide a one click download, which materialises a working IDE, workspace and target platform on your box. The git repository should already be connected with our gerrit instance. Also we want to start writing breaking and ignored unit tests for defects so potential contributors can easily reproduce a problem and see how our test framework works. Let's see if we can make contributing and fixing bugs simple and fun.
Another topic is to provide an alternative for debugging Xbase-languages. Currently they work through JSR-045 which is great as long as you run your code in a standard JVM. Unfortunately JSR-045 isn't supported by Android's Dalvik-VM or GWT's new SuperDevMode. We need to come up with a solution for this as well.
Finally I want to mention that there is now a package for "Java and DSL Developers" on the Eclipse download page. It doesn't have a neat welcome page so far but it's a one-stop-shopping for people who want to get started with Xtend or Xtext (or both).

Monday, June 18, 2012

Vert.x and Xtend

Vert.x is a framework for asynchonous, scalable, concurrent applications. It’s conceptually very similar to node.js but runs on the JVM leveraging its native support for multiple threads.

Its programming model is based on a tell don't ask paradigm, that is you never wait for responses (and thereby block the current thread), but tell what to do as soon as a response is available by passing a handler. It also isolates state (even static one) so no locking is required.

Vert.x comes with special APIs for Java, JavaScript, Ruby and Groovy. They also plan to support Scala and Python.

So what about Eclipse's Xtend?


Xtend is not just another JVM language but an alternative way to write Java applications. It translates to comprehensible Java source code and unlike other JVM languages Xtend is 100% interoperable with Java and is designed to work great with existing Java APIs. That’s why no special API for Xtend is required.

The language is statically typed and features very advanced IDE support which tightly integrates with Java projects. A release of Xtend with lots of cool new features (e.g. debugging support) is just a couple of days away (June 27).

Some Examples


I have converted the Java examples shipped with vert.x to Xtend. The code is on github and is a fully working Eclipse project including working launch configurations to run and debug all the examples. If you are used to working in Eclipse, this is an easy way to try Vert.x : Just clone & import (using the "Import existing Projects into workspace" wizard) and you are done (Thanks to Doug for explaining the setup).

In the following I want to compare a couple of Java code snippets with their equivalent Xtend code, to demonstrate the expressiveness.

Https Example


The https example consists of two classes one for the client and one for the server. The client simple executed a get request on port 4443 and the server 'localhost' and prints the received data to System.out. Here's the Java code:
// Java
@Override
public void start() {
  vertx.createHttpClient()
    .setSSL(true)
    .setTrustAll(true)
    .setPort(4443)
    .setHost("localhost")
    .getNow("/", new Handler<HttpClientResponse>() {
      public void handle(HttpClientResponse response) {
        response.dataHandler(new Handler<Buffer>() {
          public void handle(Buffer data) {
            System.out.println(data);
          }
        });
      }
    });
  }
The Java API allows to configure the HttpClient using chained calls to setter methods. The last call is the get-request (getNow) where the path as well as a response handler is provided. Instead of blocking the current thread and waiting for the response you just tell what to do when the response is available. The Java API expects an instance of Handler<HttpClientResponse> for that.

Xtend allows to use the very same API with the following code:
// Xtend
override start() {
  vertx.createHttpClient => [
    SSL = true
    trustAll = true
    port = 4443
    host = "localhost"
    getNow("/") [
      dataHandler [ data |
        println( data )
      ]
    ]
  ]
}
First an http client is created, instead of using the chained setters (we could), we use the with-operator (=>) which allows us to use and initialize the http client from the left hand side within a lambda expression (the block in squared brackets). Within the lambda the HttpClient is bound to the implicit variable 'it', which like the self reference 'this' can be omitted when used as a receiver.
Next we call the setters using assignments, that is the expression
    SSL = true
is translated and equivalent to
    it.setSSL(true)
The interesting part is how we pass the response handler in Xtend :
    getNow("/") [
      dataHandler [ data |
        println( data )
      ]
    ]
The call to getNow(String, Handler<HttpClientResponse>) is done by passing just the string in the parentheses and a lambda expression right after the call. You need to understand two things here:
  1. If the last argument of a feature call is a lambda expression it can be passed after the method call.
  2. A lambda expression automatically coerces to the expected target type if it's an interface with just one method (which is a common idiom not only in vert.x).
Within the response handling a data handler is registered by calling setDataHandler(Handler<Buffer>) on the response object. Note that since this method gets just one lambda expression passed you don't have to write the parenthesis (in Xtend empty parenthesis are optional). Also note, that this time we gave the parameter a name (data) since I found it sightly more readable than :
    getNow("/") [
      dataHandler [
        println( it )
      ]
    ]
The Java implementation of the server prints out the header keys to the console and returns a tiny document:
// JAVA
public void start() {
  vertx.createHttpServer()
    .setSSL(true)
    .setKeyStorePath("server-keystore.jks")
    .setKeyStorePassword("wibble")
    .requestHandler(new Handler<HttpServerRequest>() {
      public void handle(HttpServerRequest req) {
        System.out.println("Got request: " + req.uri);
        System.out.println("Headers are: ");
        for (String key : req.headers().keySet()) {
          System.out.println(key + ":" + req.headers().get(key));
        }
        req.response.headers().put("Content-Type", "text/html; charset=UTF-8");
        req.response.setChunked(true);
        req.response.write("<html><body><h1>Hello from vert.x!</h1></body></html>", "UTF-8").end();
      }
    }).listen(4443);
  }
Translated to Xtend and applying the same patterns we used for the client this looks like the following:
// Xtend
override start() {
  vertx.createHttpServer => [
    SSL = true
    keyStorePath = "server-keystore.jks"
    keyStorePassword = "wibble"
    requestHandler [
      println("Got request: " + uri)
      println("Headers are: ")
      for (it : headers.entrySet) {
        println(key + ":" + value)
      }
      response.headers.put("Content-Type", "text/html; charset=UTF-8")
      response.chunked = true
      response.write('''
        <html>
          <body>
            <h1>Hello from vert.x!</h1>
          </body>
        </html>
        ''', "UTF-8").end
      ]
    listen(4443) 
  ]
}
There are two things worth mentioning in addition to what we've discussed in the first example:
  • You can use the variable name it every where. For instance in a for loop like in the code snippet above.
  • Xtend supports multiline string literals. The common literals using single quote or double quote can be multiline as well, but by using triple single quotes you get smart whitespace handling. That is the indentation before the tag will be pruned for all lines, i.e. the result will be well formatted. Also the triple quotes allow for having interpolation expressions, which are not used in this example.

Can we do even more?


Although the standard Java API already works very well there's room for special Xtend API. Vert.x for instance communicates with JSON objects a lot, which you might want to declare easily. Xtend doesn't support native JSON syntax, but you can design powerful APIs using a combination of extension methods and operator overloading. I added just three methods to be able to construct instances of vert.x's JsonObjects like this:
class JsonExample extends Verticle {
  
  override start() {
    val eb = vertx.eventBus
    val pa = 'vertx.mongopersistor'
    val albums = _(
      _(
        'artist'- 'The Wurzels',
        'genre'- 'Scrumpy and Western',
        'title'- 'I Am A Cider Drinker',
        'price'- 0.99,
        'categories'- _('action', 'comedy')
      ),
      _(
        'artist'- 'Vanilla Ice',
        'genre'- 'Hip Hop',
        'title'- 'Ice Ice Baby',
        'price'- 0.01
      ),
      _(
        'artist'- 'Ena Baga',
        'genre'- 'Easy Listening',
        'title'- 'The Happy Hammond',
        'price'- 0.50
      ),
      _(
        'artist'- 'The Tweets',
        'genre'- 'Bird related songs',
        'title'- 'The Birdy Song',
        'price'- 1.20
      )
    )
    
    // First delete everything
    eb.send(pa, _('action'- 'delete', 'collection'- 'albums', 'matcher'- _()))
    eb.send(pa, _('action'- 'delete', 'collection'- 'users', 'matcher'- _()))
    
    // Insert albums - in real life price would probably be 
    // stored in a different collection, but, hey, this is a demo.
    
    for (album : albums) {
      eb.send(pa, _(
        'action'- 'save',
        'collection'- 'albums',
        'document'- album
      ))
    }
    
    // And a user
    eb.send(pa, _(
      'action'- 'save',
      'collection'- 'users',
      'document'- _(
        'firstname'- 'Tim',
        'lastname'- 'Fox',
        'email'- 'tim@localhost.com',
        'username'- 'tim',
        'password'- 'password'
      )
    ))
  }  
}
These are the three extension methods:
  def static <T> Pair<String,T> operator_minus(String key, T value) {
    new Pair(key, value)
  }
  
  def static JsonArray _(Object ... entries) {
    val result = new JsonArray
    for (e : entries) {
      switch e {
        String : result.addString(e)
        Number : result.addNumber(e)
        Boolean : result.addBoolean(e)
        JsonObject : result.addObject(e)
        JsonArray : result.addArray(e)
      }
    }
    return result
  }
  
  def static JsonObject _(Pair<String, ?> ... entries) {
    val result = new JsonObject
    for (e : entries) {
      switch value : e.value {
        String : result.putString(e.key, value)
        Number : result.putNumber(e.key, value)
        Boolean : result.putBoolean(e.key, value)
        JsonObject : result.putObject(e.key, value)
        JsonArray : result.putArray(e.key, value)
      }
    }
    return result
  }

Sunday, June 10, 2012

Xtend - The Movies Example

The upcoming release of the new version of Xtend is just a couple of days away (June 27). Although the technical (OSGi) version is 2.3, for me it's really more like a 1.0 release. It now has everything you need to write beautiful Java programs, like the little movies example we have been using in some workshops we did recently.

The movies example is also included in the example project that will be shipped with the Eclipse plug-in and is about reading a file of movie data in and doing some queries on it.

The Data

The movie database is a plain text file (data.csv) with data sets describing movies. Here's an example data set:

Naked Lunch  1991  6.9  16578  Biography  Comedy  Drama  Fantasy

The values are separated by two spaces. The columns are :

  • title
  • year
  • rating
  • numberOfVotes
  • categories (where any number of categories is allowed)

Let's start by declaring a data type Movie reflecting the data set:

@Data class Movie {
  String title
  int year
  double rating
  long numberOfVotes
  Set categories 
}

The @Data annotation will turn this class into a value object, that is the compiler will create

  • a getter-method for each field,
  • a hashCode()/equals() implementation,
  • implementation of Object.toString() and
  • a constructor accepting values for all fields in the declared order.

Parsing The Data

Let's now define another class which reads the text file into a list of movies so that we can do some analysis on the data. We will access the data from within a JUnit test, so simply initializing a field is appropriate:

import java.io.FileReader
import java.util.Set
import static extension com.google.common.io.CharStreams.*

class Movies {

  val movies = new FileReader('data.csv').readLines.map[ line |
    val segments = line.split('  ').iterator
    return new Movie(
      segments.next, 
      Integer::parseInt(segments.next), 
      Double::parseDouble(segments.next), 
      Long::parseLong(segments.next), 
      segments.toSet
    )
  ]
}

The field's type (List) is inferred from the expression on the right hand-side and we want the field to be final, so we declare it as a value using the keyword code val.

The initialization on the right hand side first creates a fresh instance of java.io.FileReader. Then the method readLines() is invoked on it. But if you have a look at FileReader you won't find such a method. It's in fact a static method coming from Google Guava's CharStream and is imported as an extension :

import static extension com.google.common.io.CharStreams.*

CharStream.readLines(Reader) returns a List on which we call another extension method called map. That one is defined in Xtend's runtime and is always imported and therefore automatically available on all lists. The map-method expects a function as the parameter. It invokes that function for each value in the list and returns a list containing the results of the function invocations.

Function objects are created using lambda expression (the code in squared brackets). Within the lambda we process a single line from the text file and turn it into a movie by splitting the string using the separator and calling iterator() on the result. As you might know java.lang.String.split(String) returns a string array (String[]). But as Xtend auto-converts arrays to lists when needed, we can call iterator() on it.

val segments = line.split('  ').iterator

Now we use the iterator to create an instance of Movie:

return new Movie (
  segments.next, 
  Integer::parseInt(segments.next), 
  Double::parseDouble(segments.next), 
  Long::parseLong(segments.next), 
  segments.toSet
)

Answering Some Questions

Now that we've the text file turned into a List, we are ready to do some queries on it. We use JUnit to make the individual expressions executable.

Question 1: How Many Action Movies Are Contained?:

@Test def void numberOfActionMovies() {
  assertEquals(828, 
    movies.filter[categories.contains('Action')].size)
}

It's using the extension method filter to filter the movies. The lambda expression checks whether the current movie's categories contains the entry 'Action'. Note that unlike the lambda we used to turn the lines in the file into movies, we haven't declared a parameter name this time. We could have given the parameter an explicit name 'movie' by writing the following:

assertEquals(828, movies.filter[movie | movie.categories.contains('Action')].size)

But if we leave out the name and the vertical bar the variable is automatically named 'it' which (like this) is an implicit variable. That's why we can either write

assertEquals(828, movies.filter[it.categories.contains('Action')].size)

or just

assertEquals(828, movies.filter[categories.contains('Action')].size)

Lastly we call size on the resulting iterable, which again is an extension method (java.lang.Iterable doesn't define such a method).

Question 2: What's The Year The Best Movie From The 80ies Was Released.

@Test def void yearOfBestMovieFrom80ies() {
  assertEquals(1989, 
    movies.filter[(1980..1989).contains(year)].sortBy[rating].last.year)
}

Here we filter out all movies where the year is not included in the range from 1980 to 1989 (the 80ies). The range-operator (..) again is an extension defined for two ints and returns an instance of org.eclipse.xtext.xbase.lib.IntegerRange.

The resulting iterable then is sorted by the rating of the movies. Since it's sorted in ascending order, we take the last movie from the list and return its year.

We could have sorted descending and take the head of the list as well (note the minus sign):

movies.filter[(1980..1989).contains(year)].sortBy[-rating].head.year

Btw. the calls to movie.year as well as movie.categories in the previous example of course access the corresponding getter methods, which were generated because of the @Data annotation.

Question 3: The Sum Of All Votes Of The Top Two Movies

@Test def void sumOfVotesOfTop2() {
  assertEquals(47_229, 
    movies.sortBy[-rating].take(2).map[numberOfVotes].reduce[a, b| a + b])
}

First the movies are sorted by rating, then we take the best two. Next the list of movies is turned into a list of their numberOfVotes using the map function. Now we have a List which can be reduced to a single Integer by adding the values.

Thursday, May 31, 2012

Distance / Time = Speed

I blogged about introducing a Distance datatype using Xtend some time ago, which allows you to write the following:


@Test def distances() {
  assertEquals(15.km, 13.km + 2_000.m)
  assertEquals(30.km, (13.km + 2_000.m) * 2)
}


We've enhanced this example a bit and put it into the Xtend tutorial project, which you can materialize into your workspace using Eclipse's example wizard.

We added two more datatypes Time and Speed, so that you now can write things like this:


@Test def speed() {
  assertEquals(42.km/h, (40_000.m + 2.km) / 60.min)
}


The datatype Time is defined similarly to the Distance type. It defines operators and some static methods, which when imported as extension method allows you to write things like 60.min etc.
In order to be able to divide some Distance by some Time (i.e. create Speed), you need to define a static operator like so :


@Data class Speed {
  BigDecimal mmPerMsec

  def static operator_divide(Distance d, Time t) {
    new Speed(d.mm / t.msec)
  }
}


Just import this as an extension method and you are able to write :
  (40_000.m + 2.km) / 60.min

Finally we also want to write Speed literals like 42.km/h.

Can you guess how this is done?

(If not, it's in the example :-)
Eclipse updatesite: http://download.eclipse.org/modeling/tmf/xtext/updates/composite/latest/ )

Friday, April 27, 2012

Xtend - New Language Features coming in M7

The team has been busy adding useful new features to Xtend (and all other languages built on top of Xtext's JVM-support). The upcoming M7 build (May 9) will come with the following enhancements:

"With"-Operator

A new operator '=>' has been added to the language and a corresponding extension method for java.lang.Object on the left hand side and a lambda expression on the right hand side. 
The with operator allows you to write:

new JTextField => [
  text = 'My Text'
]

Think of it as a let-expression, which allows for binding any object to the scope of the block, in order to do side-effects in it. Very handy when initializing objects.

Properties

A new annotation @Property will generate a Java-Bean-style getter and setter (if the field is not final) for an annotated field.

class Person {
  @Property String firstName
  @Property String lastName
}

The field itself will be renamed to _fieldname, to make one accesses the getter (resp. setter) when using the property syntax. OF course a getter or setter is only generated when not explicitly defined.

Data Classes (Value Objects)

Another annotation @Data, will turn an annotated class into a value object class. A class annotated with @Data has the following effect:
  1. all fields are flagged final, 
  2. getter methods will be generated (if not existent), 
  3. a constructor will be generated (if not existent),
  4. equals(Object) / hashCode() methods will be generated (if not existent),
  5. a toString() method will be generated (if not existent). 
Example:

@Data class Person {

  String firstName
  String lastName
}

For now the processing of the two annotations is hard coded into the compiler. However as described in this bugzilla, we want to add support for library level annotation processing. This will allow for adding other annotations like @Delegate etc. Also we want to make this very easy so you can easily define your own project-specific annotations. Unfortunately this will not make it into the upcoming release.

Multiple Classes in One File

You can now have any number of classes in a single file. Also the name of the first class must no longer match the file's name. But still if it matches it will be renamed in a rename refactoring.

Enhanced Field Declarations

Type inference for fields is now working, also the val and var keywords are available. 
Example:

class Person {
  @Property val firstName = 'Hans'
  @Property var lastName = 'Meier'
} 

Other areas we've been working on

Besides enhancing the language, we put a lot of effort into the IDE as well. Several new features like for instance a quick assist to add method declarations have been added. Also Sebastian is working on a rewrite of the type inference and linking engine, since the current implementation turned out to be a bit slow in certain situations.

Tuesday, March 20, 2012

Xtend 2.3 beta version available

Today we announce the availability of the first beta version for the planned release in June. As you might know Xtend is a statically typed, functional and object-oriented programming language targeting the Java Virtual Machine. As opposed to other Java alternatives Xtend compiles to readable Java source code, provides state-of-the-art Eclipse integration and is 100% compatible with existing Java libraries and frameworks.
Besides many bug fixes, performance improvements and some minor language enhancements (number literals, varargs, etc.), the big leap has been done on the tooling side. 
Debugging through Xtend and Java sources now works transparently side by side. As Xtend generates Java source code, the user can even switch between the generated Java source and the original Xtend source while in a debugging session. This equivalence of languages is also stressed by a special Eclipse view that allows to inspect which parts of the generated Java code are derived from which segments of Xtend code.

The new Eclipse plug-in for Xtend now integrates seamlessly with Eclipse’s Java Development Tools. No matter whether you click on a stack frame in a printed exception, on a failing unit tests, or on some search result in the call hierarchy, find references or the type hierarchy view: If the target element has been implemented in Xtend, the Xtend editor will open up and select the correct source location. 
In case you want to see the generated Java source code, there’s the new ‘Generated Code’ view. It shows the generated code and marks the correct ranges corresponding the current selection in the Xtend editor. With that you can understand how Xtend is translated to Java in detail. Looking at the generated Java will help you getting familiar with the language.

See the "New & Noteworthy" page for more details and more cool new features.
The final release is planned for June 27 as part of Eclipse Juno, this year’s Eclipse release train. Till then we want to focus on stabilizing, improving performance and making sure nothing gets into the way of a great user experience. We are extremely happy with the beta version, and enjoying working on it and in it on a daily basis. There’re still a lot of things to do and we hope to get a lot of feedback from the community, so we are able to address any outstanding issues till June.
The beta version is now available for through the following Eclipse p2 update site : http://download.eclipse.org/modeling/tmf/xtext/updates/composite/milestones/

Friday, February 17, 2012

Lambdas and functional interfaces in Java 8

Lambda's in Java 8 are going to be very nice. I like how they integrate with the existing type system. They automatically convert to so called interface types (previously SAM types), which are interfaces where only one method needs to be implemented. That allows to just use e.g. Google Guava right away without any modifications.

Also this means that there are no types like Scala's Function23 and you even can have lambdas with 24 arguments (not saying that this is a particularly good idea :-)).

The most commonly used functional interfaces will likely come with java.util.* since they are needed there. So hopefully we won't be forced to redeclare the obvious functional interfaces all over the place. I consider such a commonly used set of generic interface types important since otherwise we will end up with redefining them in every project.


The downside of not having explicit "function types" is that writing signatures will still be quite clumsy.

To declare a higher-order method like e.g. 'map' on java.lang.Iterable, in Java you would have to invent some functional interface and then write :

public <R> Iterable<R> map(Function<? super T, ? extends R> predicate)

Compared to Xtend, which also supports the conversion to functional interfaces, there is a special type signature for functions, which will get the generics (i.e. upper and lower bounds) straight for you. So in Xtend you can just write the following instead :

def <R> Iterable<R>  map( (T)=>R predicate )

(T)=>R really is just a short-form of Function<? super T, ? extends R>

Using this type signature in casts also allows for easily convert from one functional interface to another. Also you can declare lambdas without any context type information. In Java 8 the following will not be possible, since the context type (java.lang.Object) is not an interface type:

Object myFunction = (String s)-> s.toUpperCase();

So instead you'd write:

Function<? super String,? extends String> myFunction = s -> s.toUpperCase()

In Xtend you can instead just use type inference and write :

val myFunction = [String s| s.toUpperCase()]

So as you can see having a syntactical short form for type signatures like Xtend would improve readability of signatures a lot and would also help developers getting the upper- and lower bounds right. But even without this using auto conversion to interface types is a great way to add lambdas to Java.

Wednesday, January 11, 2012

I like free beer!

Did you know about http://99-bottles-of-beer.net?
They list programs generating lyrics for a song about beer in 1440 different programming languages (it will be 1441 very soon ;-)). These are the lyrics to generate.

So here is a version written in Xtend:


It uses a couple of interesting features:
Seriously, I think this is one of the most concise and readable versions. Compare yourself.

Wednesday, December 21, 2011

Groovy, Scala, Java, Xtend - an UPDATED stupid comparison

This is an update to yesterday's post, based on feedback I got so far:

Measurement

Henning suggested that the number of iterations is too small:

10000 iterations are probably not enough for a comparison: If I go from 10k to 100k iterations, the Scala version needs 5x time -- the Java version only 2x.

Indeed. Here's what I got when using 1M iterations:

  • Java (the pretty version):
    Took : 245 ms, number of elements : 3000000
  • Xtend :
    Took : 278 ms, number of elements : 3000000
  • Xtend (using switch - see below) :
    Took : 298 ms, number of elements : 3000000
  • Scala (using for comprehensions) :
    Took : 5140 ms, number of elements : 3000000
  • Scala (using while loops) :
    Took : 931 ms, number of elements : 3000000
  • Scala (using while loops and java.util.collections - see below) :
    Took : 315 ms, number of elements : 3000000
  • Groovy (using << operator - see below):
    Took : 1683 ms, number of elements : 3000000

Groovy

Thorsten and Jochen pointed out that I used the wrong operator for adding new elements to a list. I should use '<<' instead of '+=' since the latter would create a new list for the single elements before adding them. I've fixed this and the Groovy program is much faster now.

Jochen also pointed out that the comparison is unfair since, because of the dynamic dispatch Groovy does heavy caching assuming that a method is invoked for the same type of argument most of the time.

My initial idea was to do a comparison where Groovy has a strength (i.e. dynamic dispatch). After all the other examples also do dispatching at runtime. The Java and Scala version don't call another method, but since Xtend does so and is as fast as Java I'd say this extra call doesn't change much.

Jochen also states:

Imagine a class with those three foo methods written in Java. Then in Groovy you can still run your test. I dare to say that in Xtend you cannot make this work without a dispatcher method somewhere - and your dispatch keyword is implying that - thus I assume you cannot make this then work using a Java class.


I think this is actually a big problem with Groovy. Although it's syntax might look a bit like Java it behaves totally different.
In contrast Xtend binds statically just like Java and in fact a multi method in Xtend behaves always the same no matter if you call it from Java or Xtend.

He further says

But let us not stop here... let us assume that you write the base class in Java, where it knows foo(String) foo(Object) and foo(Boolean). Using this class the Integer variant would call the foo(Object) method in your code. Now extend that class in Java with a foo(Integer) method and Groovy would no longer call foo(Object) but foo(Integer).
I doubt you can easily simulate that case.


I can indeed not do that in Java. But I can do that with Xtend and it still behaves as expected no matter form what language you'd call that code.

Scala

Jan said:

I rewrote your little program to use while loops and the java utils collections and the scala version was as fast as java - but nearly as ugly to :-D

Here's the updated Scala version with while and java.util.collections, which is now almost as fast as the Java version:
object Scala extends Application {
  val absoluteResult = new ArrayList[Any]()
  val before = System.currentTimeMillis()
  var i =0
  while (i<1000000) {
    i = i+1
    val result = List("foo", 23, true).iterator
    while (result.hasNext) {
      absoluteResult.add(foo(result.next))
    }
  }
  println("Took : "+(System.currentTimeMillis() - before)
      +" ms, number of elements : "+absoluteResult.size)
  
  def foo(obj : Any) =
    obj match {
          case _:String => "String"
          case _:Boolean => "Boolean"
          case _:Integer => "Integer"
          case _ => throw new IllegalArgumentException()
    }
}

Clojure

Stefan did a nice little example in Clojure. It doesn't use any mutable collections but uses a pure functional style:

(defn foo [x]
(cond
(number? x) "Number"
(string? x) "String"
(= (class x) Boolean) "Boolean"))

(time (println (count 
(map foo 
(apply concat 
(repeat 10000 ["foo" 23 true]))))))
On his machine the Java example takes '31ms' and the Clojure program prints

Prints:
30000
"Elapsed time: 194.046477 msecs"

Xtend

An alternative way to do the dispatch in Xtend is using type guards in switch,
which doesn't make a huge difference performance-wise :

class XtendWithSwitch {
  def static void main(String[] args) {
    val absoluteResult = newArrayList()
    val before = System::currentTimeMillis()
    for (times : 0..1000000) {
      val result = newArrayList('foo', 23, true)
      for (y : result) {
        absoluteResult += foo(y)
      }
    }
    println("Took : "+(System::currentTimeMillis() as int - before)
      +" ms, number of elements : "+absoluteResult.size)
  }

  def static foo(Comparable comp) {
    switch(comp) {
      String : 'String'
      Boolean : 'Boolean'
      Integer : 'Integer'
      default : throw new IllegalArgumentException()
    }  
  }
}

Java


Finally based on Henning's suggestion I beautified the Java version a bit using Guava and static imports:

public static void main(String[] args) {
  List<Object> absoluteResult = newArrayList();
  long before = System.currentTimeMillis();
  for (int i=0; i < 1000000; i++) {
    for (Object y : newArrayList("foo", 23, true)) {
      absoluteResult.add(foo(y));
    }
  }
  System.out.println("Took : "+(System.currentTimeMillis() - before)
    +" ms, number of elements : "+absoluteResult.size());
}

static String foo(Object s) {
  if (s instanceof String) {
    return "String";
  } else if (s instanceof Boolean) {
    return "Boolean";
  } else if (s instanceof Integer) {
    return "Integer";
  } else {
    throw new IllegalArgumentException();
  }
}

Tuesday, December 20, 2011

Groovy, Scala, Java, Xtend - a stupid comparison

Disclaimer: This is probably the worst possible way to compare execution performance. I'm posting it nonetheless since the result was significant. Judge for yourself.

Today I took some time to check out the latest Eclipse plugins for both Groovy and Scala. I mainly wanted to know how nice the tooling is and played around with it a bit. I had been doing some Scala a couple of years ago, but since the Eclipse plugin not even existed those days it was a bit too painful for me to get used to it.

Groovy's tooling looks very good. There are just a few oddities but mainly I think it's well done... in contrast to the Scala plugin (I used 2.0.0 RC4). It holds a lot of surprises. For instance, with the Scala-IDE installed you'll get Scala-related template proposals in the Java and the Groovy editor. Still Scala the language would be my personal choice if I had to decide between the two. Anyway, this post is not about language features or Eclipse-plugin quality, but about what I experienced regarding runtime performance.

I knew Groovy's performance is bad. But I expected the performance problems to diminish, if I use a scenario using dynamic dispatch and mostly untyped objects. So I wrote the following brain dead code:

class Groovy {

  public static void main(String[] args) {
    def absoluteResult = []
    def before = System.currentTimeMillis()
    for (times in 1..10000) {
      def result = ['foo', 23, true]
      for (y in result) {
        absoluteResult += foo(y)
      }
    }
    println("Took : "+(System.currentTimeMillis() - before)
      +" ms, number of elements : "+absoluteResult.size);
  }

  static String foo(String s) {
    'String'
  }
  
  static String foo(Boolean s) {
    'Boolean'
  }
  
  static String foo(Integer s) {
    'Integer'
  }

}

It doesn't do anything interesting but leverages Groovy's built-in way of resolving overloaded methods using the runtime type. I thought it's fair to use this feature in a comparison, also because Xtend's dispatch methods have the same behavior. The result of the code above would be a list containing the string 'String', 'Boolean', and 'Integer' each 10.000 times.

When I run this code on my machine, it prints something like the following:

Took : 2025 ms, number of elements : 30000

A possible Xtend version

This is how I could achieve the same using Xtend:

class Xtend {
  def static void main(String[] args) {
    val absoluteResult = newArrayList()
    val before = System::currentTimeMillis()
    for (times : 1..10000) {
      val result = newArrayList('foo', 23, true)
      for (y : result) {
        absoluteResult += foo(y)
      }
    }
    println("Took : "+(System::currentTimeMillis() - before)
           +" ms, number of elements : "+absoluteResult.size)
  }

  def static dispatch foo(String s) {
    'String'
  }
  
  def static dispatch foo(Boolean s) {
    'Boolean'
  }

  def static dispatch foo(Integer s) {
    'Integer'
  }
}

On a first glance it looks very similar. Note, the dispatch keyword, which turns a set of overloaded methods into dynamically dispatched methods (i.e. the default Groovy behavior).
In contrast to the Groovy version this one is fully statically typed and as it turned out much faster. (Again as you see my measurement technique is everything but professional, but given such a big difference I dare to say it's faster).

It prints something like:

Took : 43 ms, number of elements : 30000

I also did a Scala version:


object Scala extends Application {
  val absoluteResult = MutableList[Any]()
  val before = System.currentTimeMillis()
  for (times <- 0 until 10000) {
    val result = List("foo", 23, true)
    for (y <- result) {
      absoluteResult += foo(y)
    }
  }
  println("Took : "+(System.currentTimeMillis() - before)
      +" ms, number of elements : "+absoluteResult.size)

  def foo(obj : Any) =
    obj match {
          case _:String => "String"
          case _:Boolean => "Boolean"
          case _:Integer => "Integer"
          case _ => throw new IllegalArgumentException()
    }
}

I got this kind of result:

Took : 130 ms, number of elements : 30000

And finally a Java version:

public class Java {
  public static void main(String[] args) {
    List<Object> absoluteResult = new ArrayList<Object>();
    long before = System.currentTimeMillis();
    for (int i=0; i < 10000; i++) {
      List<Object> result = new ArrayList<Object>();
      result.add("foo");
      result.add( 23);
      result.add(true);
      for (Object y : result) {
        absoluteResult.add(foo(y));
      }
    }
    System.out.println("Took : "+(System.currentTimeMillis() - before)
      +" ms, number of elements : "+absoluteResult.size());
  }

  static String foo(Object s) {
    if (s instanceof String) {
      return "String";
    } else if (s instanceof Boolean) {
      return "Boolean";
    } else if (s instanceof Integer) {
      return "Integer";
    } else {
      throw new IllegalArgumentException();
    }
  }
}

Which prints:

Took : 40 ms, number of elements : 30000

Monday, December 12, 2011

Writing Android UIs with Xtend

(Update: You can find the project on github : https://github.com/svenefftinge/xtend-android-experiments )

Xtend is a great fit for Android development. Since Xtend translates to Java source code, it's very easy to use it. After you've installed the Xtend SDK and the Android Development Tools you only need to do two things to get started.
  1. In Eclipse's preferences configure Xtend's compiler to generated to the gen/ folder.
  2. Add the Xtend lib and Google Guava to your project's classpath. 
Why is it useful?
Using a combination of Xtend's powerful extension methods and closures, it's possible to come up with a very declarative API to define UI models. It takes a couple of minutes to write an API which allows for defining a UI like the following:

class AppActivity extends Activity {
 
  override void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
  
    contentView = this.linearLayout [
   
      orientation = VERTICAL
  
      view = this.textView ("Hello Android!")
  
      view = this.button ("Click Me!") [
        onClickListener = [ 
          this.textMessage('Hello you clicked me!').show
        ]
      ]
    ]
  } 
}

The API is made available by means of a static extension import. To outline the idea, here's how the button method is defined:

def static button(Context context, String text,
      (Button)=>void initializer) {
  val result = new Button(context)
  result.text = text
  initializer.apply(result)
  return result
}

Used as an extension method button can be invoked on any instance of Context. Since the last argument is a function type it can be passed after the actual method invocation:

view = this.button ("Click Me!") [
        onClickListener = [ 
          this.textMessage('Hello you clicked me!').show
        ]
      ]

Also note how you can simply assign a closure to onClickListener (which is btw. invoking setOnClickListener()). The compiler will automatically convert it to an abstract class of View.OnClickListener.
And everything is 100% statically typed!



Tuesday, November 22, 2011

What’s So Special About Xtend’s Extension Methods?

You should read this, if you are :

  • interested in new programming language concepts
  • understood how great dependency injection is
  • want to learn about some uniqueness in Eclipse Xtend

Extension Methods

Extension methods enable you to "add" methods to existing types without creating a new derived type, recompiling, or otherwise modifying the original type. In C# extension methods are a special kind of static method, but they are called as if they were instance methods on the extended type. (Wikipedia November 2011)

In Xtend you could, for instance, add a new method to java.util.List like this:

def static <T> T head(List<T> list) {

  for (element : list)

    return element

  return null

}

Which then can be used as an extension method on any instance of Iterable<T>:

newArrayList(“foo”,”bar”).head()

Using the prefix notation is much closer to how we think, read, and write. From left to right that is. Also the IDE can now provide useful proposals because the receiver is known. The readability gets even better if you use chained method invocations. For instance, let's assume you want to filter the list before obtaining the head. Using the regular infix syntax known from Java the code would like like that :

head(filter(newArrayList(“foo”,”bar”) , [e | e != “foo”]))

But reading inside out doesn’t seem to be the best way to understand what’s going on. So better use extension methods:

newArrayList(“foo”,”bar”).filter(e | e != “foo”).head

Much better, isn't it?


Static Methods Are Bad!

But wait, don’t extension methods advocate the heavy use of static methods? And isn’t that bad coding style?

Yes, often it is.

With static methods you’ll bind your code not only to the signature of a certain method but to the actual implementation. There’s no way (aside from byte code manipulation) to change the implementation without touching the client code. That’s probably not a big deal with the kind of extension methods I just showed. But what if you want to have DAO-like methods available on your domain model types? Accessing them in a static way seems totally uncool, since we wouldn’t be able to run the code with mocks or exchange the database layer easily or just fix or change something later on. That's why static methods are a bad choice most of the time.

Typically you would want to use a dependency injection container to have such services injected. This is where Xtend’s extension methods are different from the one you find in C#.

Xtend allows to use methods from local fields as extension methods.

Let’s assume we have the following Java interface:

interface SaveSupport {

  void save(Entity entity);

}

And given we have some domain model type Person which implements Entity, you can write the following code:

class Controller {


  @Inject extension SaveSupport


  def testStuff() {

    val p = new Person()

    p.name = “Fred Flintstone”

    p.save // translated to ‘this._saveSupport.save(p)’

  }

}

That’s a big deal, because now you can use an object oriented coding style but keep your domain model free from layer specific code at the same time! And everything is easily testable and can be run in different scenarios using different DI configuration. There are other unique language features in Xtend, like the template expression, but the combination of extension methods and a good dependency injection framework (Guice) really changes how you structure your software system and reason about it.