Monthly Archives: April 2012

Haxe 2.09 – WWX 2012

It was really a great pleasure to attend the WWX 2012 in Paris. The talks were extremely interesting and they really showed how much the community is growing. Several factors are contributing to that growth and I am pretty sure that one of these is the amazing development that NME is living and the features that it offers in the mobile department.

The conference was also an occasion for announcements like the new formal spelling of “Haxe” (no more “haXe”). And of course the new Haxe 2.09 that is, in my opinion, one of the best releases ever. Here is my 2 cents about why I like this release so much.

Haxe compiler service

The idea of the Haxe compiler service is really simple. Instead of restarting the compilation process (and the compiler boot strap) on each execution, the compiler is always active in a service waiting for some code to be compiled. It go further than that (otherwise the difference in performances would be minimal), it also keeps cached in memory the intermediate states of the compilation updating only the portions that are subjects to modifications.

My personal benchamarks show the following (after the first run):

project standard compilation compilation service
utest test cases (neko) 310ms (w/o generation 210ms) 110s (w/o generation 10ms)
ReportGrid charts (js) 720ms (w/o generation 590ms) 490s (w/o generation 360ms)

Since the compiler was already very fast, what really makes this feature stand out is that it accelerates auto-completion through -display considerably. I’ve not tested it myself but Nicolas claims x10 faster performances. FlashDevelop is the only IDE so far having adopted this feature transparently but it is not yet in an official build. You can still use it by launching the service this way:

haxe --wait 888

(add -v if you want more detailed information)

And compile you project this way:

haxe --connect 888 build.hxml

Of course you can customize the host/port number and the .hxml file.

JS Improvements

The first most impressive improvement in the JavaScript target is certainly the introduction of --js-modern and the consequent removal of --js-namespace. The new command option enclose the generated code into a closure that prevent the pollution of the global object with all the types defined in your application. Beside that, it adds the “strict mode” directive that can potentially enhance performances in some JavaScript contexts. Also the way that fields are now written in the generated output are more human friendly than before.
Besides the new output works wonder with Google Closure Compiler:

project plain DCE DCE + Closure Compiler
ReportGrid charts 918kb 748kb 569kb
ReportGrid charts w/ –js-modern 924kb 755kb 483kb

Then there is the new -debug implementation. What it does is mapping the source Haxe code to the JavaScript output using a source mapping file. In the browsers that support this very new feature (Chrome so far) you will be able to debug your application directly in Haxe instead of in JavaScript. That means being able to set breakpoints, inspect variable values and call stacks directly in the Haxe code.

revamped Dead Code Elimination (DCE)

My first implementation of DCE had issues under certain conditions. Nicolas took over and revamped it completely making it a lot, lot better.
Using DCE you always have to use some care preventing that portions of the code you are using in your app are not removed by accident. For example if you create an instance by using reflection and the class name, then DCE is probably going to remove that class entirely since its typing is never encountered in the code flow. To avoid that to happen you must use @:expose meta tag at either the type level or at the method level.

Anonymous Objects

The anonymous objects have seen two major improvements, the first is the possibility to use quoted fields to be able to use special characters in your field name and the addition of the optional fields.
The first is very important because now you can simply copy and paste some Json object in your code without having to worry about stripping the quotes. To access the fields with special characters you still need to use reflection.
The optional fields are really powerful for “option objects” (pretty common in the JS world) where you want to be able to define a set of key/value pairs without the need of specifying all of them.
Note that this feature only applies to constant struct, for that reason you can do this:

// assuming that the type of the argument of 'create' is : { ?x : Int, ?y : Int, ?r : Int }
 create({ x : 10, y : 7, r : 4 });
 create({ x : 20, r : 5 });
 create({});

but you cannot do this:

var options = opt(); // where opt is a function returning { x : 20, r : 5 };
create(options); // doesn't compile because not all the fields of options match the signature of the options argument

Unification of Classes

When Haxe was really young there was only one platform (neko) that was capable of accessing the system platform. With the proliferation of the new targets and the expanded possibilities to use the existing ones in different contexts, more and more implementations of the same functionalities have been spreaded over different package names (mainly neko, php and cpp). In Haxe 3 the platform specific API for these will be gone and they will be unified; in 2.09 the types have been already moved to their final destination but shortcuts were left so that the existing code doesn’t break.
The modules affected by these changes are:

Sys (was neko.Sys/php.Sys/cpp.Sys)
sys.FileStat
sys.FileSystem
sys.db.*
sys.io.*
sys.net.*

In thx there were already shortcuts to avoid platform specific packages and I guess I will have to remove them now.

Std.format

This tiny macro is a huge time saver that allows you to simplify things like this:

var s = "Hi "+name+" "+lastname+", your score is "+score;

to this:

var s = Std.format("Hi $name $lastname, your score is $score");

A lot more readable and starting with Haxe 3 it will be applied automatically to all the string definitions compacting the above to:

var s = "Hi $name $lastname, your score is $score";

You can use any Haxe expression inside the string, but if it is more complex than a simple identifier you will have to use the curly brackets format:

Std.format("list length: ${list.length}")

std package for root package

In rare occasions you might have experienced conflicts between types with the same name but that existed in the root package and in a sub-package. Suppose that you have a class def.Type referenced in your code and in the same code you want also to use the type Type. The only way to make that happen would be to create a typedef alias to Type but now you can instead just use std.Type.

haxe.Utf8

For performance reasons the String type is mapped directly to the native implementation of each target platform. The biggest implication of this choice is that the length property and the substr() method can return different results depending on the support of the UTF8 encoding in the targets. With haxe.Utf8 you can reliably obtain a consistent behavior cross-platform.

I have not covered all changes in the new release but only those that make me particularly happy :)

Vector Graphics in the Browser – WWX 2012

I have uploaded my slides (PDF) and the samples from the presentation:

… and remember, circles are bad!

The libraries presented are dhx and thx.