Brief Haxe Tutorial

I’ve thankfully had some time recently to put into learning a little Haxe, and while doing so have written up my notes into a brief tutorial: http://www.unexpected-vortices.com/haxe/brief-tutorial.html. Haven’t yet put the markdown source into git(hub|lab)|sourcehut. Feedback appreciated!

Although I’m still new to Haxe and have written relatively little code in it, I’m hoping to have captured the main strengths of Haxe, which I really like, and which I think are:

  • practical, sensible, predictable language (obeys principle of least surprise) without excessive syntactic sugar
  • Haxe isn’t “different just for the sake of being different”
  • free-software licensed, community-focused

(Well, and of course the large number of targets too.)

Do you agree with those points?

As a specific request, I could especially use some help adding more cons to go with the pros, as I’m currently enjoying my Haxe honeymoon and thus any cons are currently invisible to me at the moment. ;)

Thanks!

14 Likes

Haxe isn’t “different just for the sake of being different”

As an example of this: I remember from my Perl days operating on arrays with push, pop, shift, unshift. Folks can complain about Perl, but one of the things it’s good at is naming things. So, I recall when learning Python, and seeing append, pop, insert(0,), pop(0), I wondered “why fix what isn’t broken?”. Maybe just to be different? Same with “dict” instead of hash or map. I understand coming up with new names for new unique things, but why bother calling “a” “b”, when everyone already knows it as “a”? So, anyhow, glad to see Haxe using the usual names for things (that I’ve seen so far).

1 Like

I started with Haxe a little less than 2 years ago, and was confused at first about how to get a project going. Most tutorials are based around making a game in OpenFL or similar - which is great but when you want to make a bare-bones console app to test things out it’s a bit overkill.

I wish I’d found a tutorial like yours back then, so as a fellow newcomer to Haxe here’s a few things that would have helped me on my way when first starting to learn Haxe. Some are language basics, others are specific things that have helped me work better with Haxe.

Feel free to add, reword, ignore!

VSCode has a great Haxe extension, and one of the commands is Initialize Project. It builds out a ‘Hello World’ app with the Build task wired up to run it. It is a great way to get straight to trying something out. Just a quick way to do what your ‘getting-started’ page explains. image

For more complex projects the HXP library is a fantastic build tool, it does many things that are difficult to do with standard HXML build files. It can be thought of as a pre-build step that can run any Haxe code and compiles HXML files that are then used for the build step. It is an OpenFL project, but OpenFL is not required to use it. I built with HXML for quite a while but eventually ran into trouble handling larger projects - HXP saves some headaches when batching builds to client+server or changing targets/etc.

Haxe does almost everything at compile time instead of run time. This threw me off a bit at first. I noticed private methods becoming public in the output, and methods that required a specific parameter type not being type-checked. Essentially the Haxe compiler says ‘hey, I checked that at compile time, run time checking is slow and I already did the work!’ Which totally makes sense and works great, but only when all the code was compiled from Haxe! Building a library for a target language from Haxe means you have to validate all incoming data, be careful! Some targets (C#/Java) have specific compiler meta flags that make building libraries better/easier, Built-in Compiler Metadata - Haxe - The Cross-platform Toolkit (@:private for example).

Functions can be defined within another scope, this is very similar to how Javascript does things. Coming from a ‘pure’ object oriented (C#/Java) world I love it and hate it at the same time, but it’s just so handy I would never give it up. Quick example:

class Main {
	static function main() {
		var random:Float = 0;
		// Function within a function
		function addRandom(limit:Float) {
			random+=Math.random()*limit;
		}
		for(i in 1 ... 5)
			addRandom(i);
		trace(random);
	}
}

For array and map creation the [] init is handy:

var a = new Array<String>();
var a:Array<String> = [];
var m:Map<Int,String> = [];

If you’re trying to incorporate Haxe into an existing project in a different language, it is difficult to get clean libraries on some targets. Classes and interfaces come through great on most OO pure languages, and simple classes and anonymous structures come through great on dynamic languages. A quick way to see this is create an anonymous struct, do a few operations on it, and compile out to various targets. They’ll turn out quite different:

// javascript - easy to read!
var t = { obj : "test"};
t.obj = "test2";
console.log("src/Main.hx:5:",t);
//C# - that's not so much fun anymore
object t = new global::haxe.lang.DynamicObject(new int[]{5541879}, new object[]{"test"}, new int[]{}, new double[]{});
string __temp_expr1 = global::haxe.lang.Runtime.toString(global::haxe.lang.Runtime.setField(t, "obj", 5541879, "test2"));
global::haxe.Log.trace.__hx_invoke2_o(default(double), t, default(double), new global::haxe.lang.DynamicObject(new int[]{302979532, 1547539107, 1648581351}, new object[]{"main", "Main", "src/Main.hx"}, new int[]{1981972957}, new double[]{((double) (5) )}));

This is Haxe doing the work at compile time again, it is always consistent internally but making use of the output can be a bit odd. It totally works, and creating a library from Haxe to begin a migration from a previous project is great, but you have to build some kind of interface and validation layer to be clean and safe about it.

Function binding allows new functions from existing ones (Function Bindings - Haxe - The Cross-platform Toolkit). This comes in handy in many situations, just remember functions are first-class. I’ve found this especially handy when dealing with javascript onclick events: it’s quick job to create some helper methods, bind them to a specific object, then pass them around or set them to onclick.

enum with switch together are very useful, helping to avoid bugs (Enum matching - Haxe - The Cross-platform Toolkit). Together they force you to capture all combinations of the enum at compile time. I often use a central ‘enum’ for messaging within the code, by adding or changing the enum you can get the compiler to find all the places in the code which would break saving quite a bit of searching.

There’s plenty more tips and tricks, but this is getting too long already! Most of the super cool stuff Haxe does are part of other languages as well so I’m sure lots of people out there are saying ‘well MY favorite language already does that!’, but I’ve realized Haxe includes the best parts of every language I’ve used and it can output to many different targets as well, making it much more flexible. With this complexity comes a somewhat steep learning curve, but it has been very worthwhile.

2 Likes

Yes, I’ve heard good things about both the VSCode extension as well as the one for IntelliJ IDEA. For tutorial content though, I think it’s valuable to keep things simple — text editor + command line — and leave IDE’s until later (and they also usually have lots of their own tutorial docs, youtube videos, etc.).

Ah. Right. In the output target language. Yup. That’s one of the things I like about Haxe: that it helps you find your mistakes as soon as possible (preferable at compile-time).

Didn’t realize you could do that. Makes sense. Thanks!

Yes, like partial in Clojure.

Yes, I need to get back to this and learn more. I know I left that part of the tutorial a little abruptly empty…

Thanks for the detailed post!

I am one of the recent lovers of this language. I mainly use Java script target or game maker language. These two targets are main for me and the authors of these targets clearly tried to make them work.

Mostly cheated on macros. This is just great!