Simplifying SWT with Scala

Previously, I promised to show how to radically simplify SWT user interface development using Scala. In this article, we will examine how to do just that.

Our approach will be as follows:

I will present a Java class designed to plug into the Scala RCP application we created previously.

We will translate that Java class into Scala using as close to a 1:1 representation as is reasonable.

We will repeatedly ask, “Can we make the Scala code nicer?” and incrementally improve our example.

Our first steps will use features of the Scala language itself to make our code clearer. The last step will use a new domain-specific language (DSL) written in Scala called XScalaWT, which is a successor to the XML-based XSWT project.

I think you will be very pleased by the result.

The example application

The application we will develop is a simple converter between Fahrenheit and Celsius temperatures. Entering a Fahrenheit temperature and clicking its associated button will convert the value to Celsius and place the converted value into the Celsius field:

As we highlighted in the previous article, Scala's default constructor is simply the body of the class. Noting this fairly minor structural difference and translating the code line-by-line into Scala yields the following equivalent Scala class:

Factor out data type conversions into their own methods

When we look at the event handlers, the first thing that we notice is that 2/3 of the code is devoted to converting between data types and 1/3 of the code implements the actual algorithm.

Among dynamic language advocates, the need for explicit type conversions like we see here indicates that strong typing is a bad idea. However, Scala has a strongly-typed answer to this problem: factor out the type conversions into separate data type conversion methods. These methods are applied implicitly to anything in their lexical scope. The result is that using Scala implicit type conversions, you can have your strong safety, and enjoy clear code too.

How can we do this in our particular case?

There are two type conversions going on here:

The contents of the Text widget is converted to a Double.

The Double which is the result of the calculation is converted back to a String for display.

If we squint at the first type conversion enough, we notice that what is actually going on here is similar to Java 5 autoboxing/unboxing. We have a numeric value that is contained inside an object. We want that numeric value to be auto-unboxed for us so that we can compute based on it.

Conversion back to the String is more or less the same thing happening in reverse. In this case, we would just like our Double to behave the same way it would if it were being used inside a string concatenation expression: ie: we want the toString method to be called automatically when the expected data type (ie: the argument to setText) is a String.

Here is our example, rewritten again using Scala implicits to extend auto-unboxing to SWT Text widgets and auto-convert Double back to a java.lang.String: (For brevity, I have not repeated the package statement or the imports.)

There is one problem with this, however. As we described earlier, the data type of the anonymous function above is:

{SelectionEvent ⇒ Unit}

but the data type of #addSelectionListener is:

SelectionListener

In other words, the data type we would like to use doesn't match the expected data type.

But we just saw that Scala has a way to define implicit data type conversions so that we can specify the data type conversion once and Scala will automatically apply it for us whenever we need it. Can we use Scala implicits to automatically convert a function of type

{SelectionEvent ⇒ Unit}

to a:

SelectionListener

?

If it walks like a duck...

It turns out that we can, but in order to do it, we first have to understand a bit about how Scala implements first-class functions, and then apply Scala's static duck-typing to the problem. But don't worry, it's really easy.

In Java, if you want to define a function that you want to pass around as data, you normally define a Runnable:

It turns out that Scala actually implements its first-class functions the same way–as function objects. As gerunds, if you will; nouns that have been verbed. It's just that Scala's function objects use a different method name than Runnable does. Instead of “run”, Scala uses “apply”.

Consequently, the SelectionEvent function shown earlier in Scala is translated to something roughly like the following:

This is definitely better than we started with. We've eliminated most of the static type checking-related boilerplate code with a few strategically-written implicit conversions.

The only repetitive code that is left is all of those repeated variables, each time we make a method call.

Is there a way we can do even better?

Introducing XScalaWT

Yes, there is.

What I am about to introduce is an experimental library I've been working on for really radically simplifying SWT and Eclipse development using Scala. Its ideas are similar to XSWT, but the language syntax is Scala, not XML. This provides the following benefits:

Strong type checking. The compiler can nearly always tell you if your layout will load correctly. Sorry, you still have to make it look good yourself.

Automatic tool support. Since Scala is the language, you get content assist and compile-time syntax checking for free from the Scala Development Tools.

Integration with, and “scripting” in Scala for free (because XScalaWT is Scala).

Hierarchical code for user interface hierarchies

Notice how the hierarchical nature of XML eliminates all of the extra housekeeping variables that you use to keep Java happy? The result is that you can focus more easily and automatically on the hierarchical structure of your graphical layout rather than on the nitty-gritty of keeping the Java compiler happy.

XScalaWT takes this idea one step farther. By making the user interface language the same as the application language, the result is both a more natural syntax than even XML, and automatic tight integration with Scala code, since XScalaWT code is Scala code.

The function of the code is now fully apparent based on its structure. Scanning visually through the code is sufficient for gaining a high-level understanding of what it does, and then you can just read the parts that you actually care about.

Notice that we no longer need the implicit that allows us to treat functions as event handlers. XScalaWT does that for us automatically.

The astute reader will wonder what happened to the GridData assignments. The answer is that if you don't supply GridData of your own, and the parent has a GridLayout XScalaWT automatically uses the GridDataFactory to supply default GridData. But you can easily supply your own GridData too.

Those who don't already know Scala are certainly wondering how Composite earned itself a “contains()” method. The short answer is that Scala implicits provide a type-safe way of effectively adding methods to classes that you don' “own”. XScalaWT uses this to add the #contains method to all subclasses of Widget in the SWT hierarchy. And since implicits are lexically scoped, this method is only added if you have listed XScalaWT in your class's imports.

A bit of how this works

XScalaWT is basically one long nested vararg-style argument list of function objects along with a thin functional wrapper around SWT. There is also a fully-generic syntax supplying access to 100% of SWT's features, but this syntax depends on scala.reflect.Manifest, a library feature that is basically “internal provisional” in the current Scala release. I expect that future Scala releases will supply a fully supported way to implement the fully-generic XScalaWT syntax.

If you want to deeply understand how this works, I recommend reading the blog post I link to in the acknowledgements section along with the source code. Also, there are complete code examples in the XScalaWT distribution. If you don't know Scala yet, the book Programming in Scala by Odersky et al is excellent.

Conclusion

We have seen how using straight Scala code, we can simply SWT programming considerably.

But Scala gives us the power to define internal domain specific languages (DSLs). By using this power to define an internal DSL for SWT, we can supply the power and expressiveness previously known only to loosely-typed languages like JRuby, but with all of the benefits of a strongly-typed language that is tightly integrated with Java at the bytecode level.

If you want to try this

If you want to try the code listed in this blog, you will need the code from the previous blog, along with XScalaWT. The code is also available in Mercurial repositories over at bitbucket.org as:

After you get the code, there are two known issues I have with the SDT you should be aware of.

It often doesn't properly update classpaths when OSGI manifests are updated. The fix is usually to choose “Project | Clean…” from the menu and rebuild the whole workspace.

You have to list all bundle dependencies in Scala-based bundles. For example, if you import org.eclipse.ui, you have to explicitly import org.eclipse.swt also.

Other than this, there are a few development glitches like not always having content-assist when you should, but things seem to overall work pretty smoothly.

Project status

I have currently implemented about 85% coverage over SWT, including all of the easy parts and some of the hard parts.

Eventually, I aim to cover all of SWT and to be compatible with RAP, so you will be able to use XScalaWT to build AJAX-style Web 2.0 applications if you wish.

If you want the code, it's currently available as a Mercurial repository at http://bitbucket.org/djo/xscalawt/ and you should consider the implementation to be experimental for now.

Acknowledgements

XScalaWT's ideas derive mainly from XSWT and Glimmer, in about that order.

The implementation has more people to acknowledge than I could mention here, but I particularly want to thank the author of the blog Making SWT Shine with Scala, the Scala mailing list, and the comp.lang.scala.tools newsgroup for all providing valuable input.