Using haXe (Open Source Flash Development) Part 2

Syntax differences

I will now cover the differences between ActionScript 2, ActionScript 3, and haXe, starting with a few syntax differences between the languages:

■ new: In haXe, class constructors are not named with the name of the class but with the special identifier new. So to declare a simple class, you will do the following in haXe:

tmp9d3-72_thumb[2]

■ package: In ActionScript 2 and 3, the packages are declared in two ways. haXe adopts the popular Java syntax in order to declare packages. For instance, here’s the way to declare the class my.pack.Test:

tmp9d3-73_thumb[2]

■ for: haXe replaces both ActionScript for and for.. .in with a single for. ..in that is a way to iterate over any kind of data structure. Here are some examples; we will talk about iterators a bit later:


tmp9d3-74_thumb[2]

■ switch/break: In haXe, each case in a switch will automatically end with a break, so you can simply write the following:

tmp9d3-75_thumb[2]

As you can see, these are only small syntax differences between haXe and ActionScript. You will now continue to explore the differences, but this time you’ll explore the ones related to basic types.

Basic types differences

The basic types are the ones that are defined as part of the language. There are some differences between ActionScript 2, ActionScript 3, and haXe concerning these basic types that are explained here:

■ Int and Float: ActionScript 2 has a single Number numeric type. ActionScript 3 introduced two additional types: int and uint. In haXe, you can use either Int or Float. Here’s a small example:

tmp9d3-76_thumb[2]

■ Dynamic: ActionScript 2 has an Object type that can accept any kind of value, and Action-Script 3 has the * type that can do the same thing. Because of additional types in the haXe type system that you’ll see later in this topic, there is no Object defined in haXe; instead, there is the Dynamic type:

tmp9d3-77_thumb[2]

■ Array: Both ActionScript 2 and 3 have a single Array type. Almost all of the time, the content of an Array has the same type, and it has always been a big problem for programmers to remember which type is contained in the Array and to have to cast to the proper type every time the Array is read. To fix this major flaw in the ActionScript languages, haXe uses generics, which can be used in particular with Arrays. For instance, if you use the type Array<String> (reads "array of strings"), your Array will be able to contain only String objects, and every time you read from the Array you’ll get back a String (or null). This ensures proper code checking and good documentation. You can still use Array<Dynamic> if you want to store a mix of content in the Array. Here’s a short example:

tmp9d3-78_thumb[2]

In this section, you studied some differences in the way basic types are handled in ActionScript and haXe. I also showed that, thanks to Array generics, haXe code is more comprehensive and safer than the corresponding ActionScript code.

There are still some other changes to study, and then I will start talking about the haXe-specific features that make it such a great language.

API differences

After covering syntax and basic types differences, I’ll now discuss the API differences between haXe and ActionScript. First, recall that all the Flash Player APIs available from ActionScript 2 and 3 are

ActionScript 2

ActionScript 3

haXe

_root

N/A

flash.Lib._root

_global

N/A

flash.Lib._global

_level0

MovieClip on stage

flash.Lib.current

trace()

trace()

flash.Lib.trace

e instanceof MyClass

e is MyClass

Std.is(e,MyClass)

(MyClass)e

e as MyClass

cast(e,MyClass)

chr

String.fromCharCode

Std.chr

setInterval/clearInterval

flash. utils.setInterval/ clearInterval

see haxe.Timer

escape

encodeURIComponent

StringTools.urlEncode

eval

N/A

flash.Lib.eval

fscommand

fscommand

flash.Lib.fscommand

getTimer

getTimer

flash.Lib.getTimer

getURL

getURL

flash.Lib.getURL

getVersion

N/A

flash.Lib.getVersion

int

int

Std.int

isFinite

isFinite

Math.isFinite

isNaN

isNaN

Math.isNaN

ord

String.charCodeAt(0)

Std.ord

parseFloat

parseFloat

Std.parseFloat

parseInt

parseInt

Std.parseInt

ActionScript 2

ActionScript 3

haXe

print*

N/A

Std.print

random

N/A

Std.random

unescape

decodeURIComponent

StringTools.urlDecode

NaN

NaN

Math.NaN

Infinity

Number.POSITIVE_INFINITY

Math.POSITIVE_INFINITY

-Infinity

Number.NEGATIVE_INFINITY

Math.NEGATIVE_INFINITY

undefined

undefined

null

String()

String()

Std.string

In conclusion, most of these differences are quick to get used to using. It’s also not much work to convert an existing ActionScript application to haXe. But at this point you might still wonder why it would be useful to use haXe instead of ActionScript. I’ll cover that now and explain the haXe features that make it a very powerful programming language.

haXe features

Writing a compiler is a difficult task to do, but the most difficult part is to convince people to use it. And people have a lot of reasons for not using haXe. Here are a few quotes:

■    “ActionScript already works for me.”

■    “haXe is not official” (that is, made by Adobe).

■    “How could something free made by a few guys be better than millions of dollars invested by a big company?”

■    “But my client wants the ActionScript source code.”

■    “What if ActionScript 4 comes? How will haXe keep up with the future?”

All of these are valid points that must be taken into account when explaining haXe to someone who doesn’t know about it. One of the best arguments I have is that, even with all these valid points against haXe, a lot of good programmers are still using it. So, there must be a reason for it… I’ll now explain where haXe makes the difference.

Feature 1: libraries

“Everything that you can do in ActionScript, you can do with haXe as well.” This is important to remember. Both the Flash IDE and haXe create SWF files that run on the same Flash Player, so they have the same capabilities.

There is nothing that ActionScript can do that haXe cannot do, but on the other hand, there is nothing that haXe can do that ActionScript cannot do. So, keep in mind that in terms of the Flash API (manipulating movie clips, sound, and video), haXe is equal to ActionScript.

haXe has several kinds of libraries/APIs:

■    ThestandardAPIs (Math, Array, Xml, and so on): These are classes that are available on all haXe platforms and work the same everywhere.

■    The Flash APIs (MovieClips, Bitmaps, Sound, and so on): These offer everything that Flash Player offers in terms of capabilities.

■    The haXe API: These are some additional classes that are part of the haXe standard library. Their usage is entirely optional, and they have been added to make the life of the programmer easier. haxe.Firebug is an example of this.

■    Third-party libraries: There is a tool called haxelib that is part of the haXe distribution that enables everybody to write open source libraries and share them with other developers. There are already more than 50 of these libraries, and each of them can be easily installed on your computer by following the instructions at http://haxe.org/haxelib.

Of course, you don’t need to learn from the start how to take advantage of all these possibilities. Most of the projects need to use only the standard and Flash libraries. Butwhenyou need some additional facilities, looking first at what is available will save you a lot of time instead of rewriting it by yourself.

Feature 2: interoperability

Of course, a lot of libraries are available in ActionScript as well. Although they are not written in haXe (since both are running on the same Flash Player), it’s also possible to reuse existing ActionScript 2 and ActionScript 3 libraries in a haXe program.

In general, what you need to do first is to define some “extern” haXe classes that will enable you to compile a haXe program by using the library API. For example:

tmp9d3-79_thumb[2]

This enables you to call mylib.MyApi.foo() from your haXe program.

Since some libraries can be quite big, you can automatically generate these extern classes in two ways:

■    From a set of ActionScript 2 classes, by using a tool called aheg (http://code.google.com/ p/aheg/)

■    From a compiled ActionScript 3 library, by using haxe –gen-hx-classes library.swf

Once you’ve done this, you can use the complete library from haXe just like you would do in Action-Script, except that it’s not compiled every time. You will only have to use -swf-lib library.swf in order to integrate it as part of the final SWF.

Feature 3: type inference

In ActionScript, a lot of time is spent by programmers writing obvious things. I’ll explain what I mean with the following example:

tmp9d3-80_thumb[2]

It’s obvious in that case that s is of the type String since you assign it to a String. Here’s another example:

tmp9d3-81_thumb[2]

Here, what you know is that s is a String and that the substr method returns a String. Again, it’s obvious that h will be a String.

Guessing which type a variable will be depending on what kind of value is assigned to it is called type inference. This is entirely done by the haXe compiler, so the programmer no longer needs to write these kinds of obvious types.

Simplywriting var obj = new MyObject(); directly assigns the type MyObject to the obj variable.

In haXe, most of the time you don’t have to write any local variable type. And your code is still strictly typed.

Feature 4: typed arrays

Strict typing is an important feature for a programming language. It enables you to have an important part of your code checked by the compiler very early and thus removes a lot of testing time from the developer’s shoulders.

Also, the more strictly typed your program, the more you can modify it freely, without breaking anything, since if something is not correct in your changes, you will get a compilation error. This does not prevent logic errors, but at least a wide range of errors are avoided by using strict compilation.

But in ActionScript, the most widely used data structure, the Array, is untyped. This means it can contain any kind of type. This can be useful in some cases, but in 99 percent of the cases, programmers use arrays containing only a single type. Not being able to express this complete array type leads to a lot of casts needing to be written and breaks the program as soon as you want to change your array content—because of casts, it will compile while still being wrongly typed and hence will be broken.

Although it’s not possible with the current Flash Player to enforce that an Array must contain only one kind of type, it’s possible to check at compilation that it does. It’s called typed array, and it’s one of haXe’s features:

tmp9d3-82_thumb[2]

That previous class for the example declares a variable that is an Array containing only instances of the class User. It means that only values typed as User (or subclasses) can be stored into that array, and every time you read the array, the returned type will be User.

Things get even more powerful when combined with type inference:

tmp9d3-83_thumb[2]

In this case, the u variable will be automatically typed as User, since you know that g is a Group and that the users contains instances of the User class.

Typed arrays are very helpful for ensuring that your program is strictly typed.

Please note that although it’s not part of this topic, it’s possible to define your own classes as having either one or several type parameters. See the haXe reference manual to learn more about it.

Feature 5: ActionScript 3 generator

To satisfy your clients who need the source code of your project, the haXe compiler includes an option to generate ActionScript 3 code from the corresponding haXe code. You can simply run the following command:

tmp9d3-84_thumb[2]

This will generate all the needed .as classes in the as3_code directory. You can then compile with mxmlc by using the following command:

tmp9d3-85_thumb[2]

This is also a useful feature if you want to develop a library in haXe but use language features such as type inference and typed arrays while still making the ActionScript 3 code available for users who don’t use haXe.

Feature 6: speed

haXe improves speed over ActionScript in two domains:

■    At compilation time: Compiling large programs quickly is an important feature for a compiler. This was one of the reasons for MTASC’s success. haXe is based on the same compiler technology; it can then compile large programs faster than the Flash IDE or MXMLC, even while doing additional checking, such as type inference.

■    At runtime: haXe makes several optimizations that benefit the speed of your program. Let’s look at a few of them:

■ Fast loops: In ActionScript, you would often use for(var p=0; i<array.length;i++) for browsing the content of an array. You can do the same in haXe by using while, but most of the time you will use the short syntax for( p in array ). The main difference with ActionScript is that array.length is evaluated only once, while in haXe it’s evaluated for every loop in the script.

■    Typed arrays: In ActionScript 3, access to an array is untyped since the compiler does not know the array content. Because the haXe compiler already has this information, it can directly cast the type as soon as the array is accessed for reading. This leads to a huge performance boost, in particular when doing numerical operations on arrays of numbers.

■    Inlining: haXe adds an “inline” keyword that can be used in front of static variables and any kind of method. When this variable is used or this method called, its value or body is directly replaced in the calling code, leading to big performance improvements. Refer to the following example:

tmp9d3-86_thumb[2]

In this example, you can save the cost of a call to a method and a static field access. Since the compiler can also calculate at compile time the result of 150*500, you are also saving a multiplication here.

In conclusion, although using haXe naturally will bring some additional speed (especially in Flash 9 where things can be optimized a lot), it’s also possible to use it “inline” to fine-tune your application or library and get the most speed out of it.

Feature 7: independence

“What if ActionScript 4 comes? How will haXe keep up with the future?”

This is often a worry of people learning about haXe. People don’t want to be locked into learning a technology that will vanish a few years later.

Let’s look at how the Web is evolving. The Web is still very young; it was accessible to the public starting from 1991. And the more it’s growing, the more different technologies will be involved.

Flash is a good example of that. It started with ActionScript 1, then ActionScript 2, now ActionScript 3, and surely ActionScript 4, 5, and 6 in the next years. And nothing can guarantee you that the things that you’re doing now will be compatible with what will be available in five years. Actually, the only language that can compile to Flash 6, 7, 8, and 9 is not a version of ActionScript but haXe.

In five years from now, Flash might be crushed by Silverlight (although I don’t think so) or by another technology.

The whole idea behind haXe is to support the most popular client web platforms, which are currently Flash 6 to 9 and JavaScript. However, the Web will evolve in the upcoming years, and haXe will adapt to it. Its strength is that the language has been designed from the beginning to be able to run on several platforms.

haXe is independent from any technology or company. It’s written by developers for developers in order to ensure that every haXe developer will get maximum freedom when choosing the platform on which she wants to build her application.

Feature 8: and much more …

It’s difficult to list all the advantages of haXe here, so the following is a short list that you can look at more completely in the haXe reference manual:

■ Enums: You can declare an enum, which is a type that can have a limited set of values with optional parameters, as the following example shows:

tmp9d3-87_thumb[2]

■ Anonymous objects and typedef: You can declare some anonymous object and strictly type them:

tmp9d3-88_thumb[2]

■ Function types: You can declare strictly typed function types by listing the arguments and return types:

tmp9d3-89_thumb[2]

■ Optional arguments: You can specify that some method arguments are optional:

tmp9d3-90_thumb[2]

■    You can define your own iterators for your classes so they can be used with haXe for syntax.

■    You can use conditional compilation to define some specific behavior depending on platform or compilation flags:

tmp9d3-91_thumb[2]

 

tmp9d3-92_thumb[2]

Summary

haXe includes a carefully chosen set of features that can enhance the type safety of a program, improve the comfort of the programmer, and increase the application’s speed while still allowing you to run the same code on different platforms.

haXe is thus independent from current technologies and will continue to support the leading web platforms in the future, with maximal interoperability in mind. Investing time in haXe is rewarding for the programmer, since he’s not being locked in to a specific platform.

The future of haXe is guaranteed by the fact that it’s open source and used by many professional programmers who are helping to improve it by writing libraries, reporting bugs and fixes, and experimenting with haXe on new platforms that might be the future of the Web. You can learn much more about haXe by visiting the official haXe website at http://haxe.org.

Next post:

Previous post: