Brief Notes on Haxe

John Gabriele

2019-02

Some brief notes on Haxe, currently under construction.

Links

Languages arguably comparable to Haxe include Dart, Kotlin, Reason, and Swift.

More links:

Getting Started

Install

If you don’t have any preference, use Haxe 4 with the HashLink target. See this Getting-Started doc.

Note that the name “HashLink” can refer to the haxe output target (haxe -hl, yielding HashLink bytecode) or to the HashLink VM.

Nicknames for the two distinct HashLink usage patterns are:

Note that in both cases, you get the same HL runtime. See the HL site for more info.

Editor Setup

Geany works with Haxe out of the box.

(The Emacs Haxe mode is pretty old.)

See also this list of editors and IDEs.

hxml files

Since some haxe build commands may contain numerous arguments which you’d rather not have to laboriously type every time you build, you can create .hxml (“haxe em ell”) files that contain those args. As a simple example, for a typical hello world program, you might build and run it like so:

haxe -main Main --interp

To avoid having to type that out every time, you can create an interp.hxml file containing:

-main Main
--interp

Then you can run

haxe interp.hxml

and get the same results.

Haxelib

The Haxe online package repo and also the library management command line tool are both called “haxelib” (see the haxelib docs). See also haxelib --help.

Packages/projects you install via haxelib are often named lowercase with hyphens if necessary. A package file itself is a .zip file, and its haxelib.json file is the package config file.

By default, haxelib installs and unpacks packages into ~/haxelib. This is your local haxelib-installed packages repo. Haxelib can also handle project-specific repos.

Language Basics

Modules

Haxe packages correspond to directories, and Haxe modules correspond to .hx files. Package names are lowercase and may contain underscores. Module names are capitalized and CamelCase. Modules contain types, and type names are also CamelCase.

For example, in foo/bar/Baz.hx, the module Baz resides in the foo.bar package (and at the top of Baz.hx it says package foo.bar;). The fully-qualified module name is foo.bar.Baz.

In general, you access the types in a module like so: foo.bar.{module-name}.{type-name}. Often though, the Baz.hx module will contain only the Baz class. To avoid having to type foo.bar.Baz.Baz for the class, for this special case Haxe lets you use the shorthand foo.bar.Baz to mean foo.bar.Baz.Baz.

Importing a module allows you to use its unqualified module name (without package). You can use modules without importing them (XXX?), but then you’d have to fully-qualify them with their package name.

import foo.bar.Baz;

// then access `foo.bar.Baz` as just `Baz`.

If your module contains more than one type, any types named differently than the module are called “sub-types”. For example:

TODO

To use them from your code:

TODO

Notice that public subtypes … XXX get referred to as foo.bar.Moo, rather than foo.bar.Baz.Moo, as if you’d created a foo/bar/Moo.hx module ??. XXX This can be handy as you don’t have to create multiple tiny files… (What? How would you know that Moo came from foo.bar.Baz??)

When you import a module, you get all of its types (the one named after the module, as well as all subtypes).

classpath? XXX

Purpose of haxe -lib ...? XXX

Using Your Own Modules

In your Main.hx file, near the top:

import foo.bar.Baz;

Then have a foo/bar/Baz.hx file containing:

package foo.bar;

class Baz {/*...*/}

Standard Library

Not listing the language-/target- specific standard libraries, we have:

Any.hx
Array.hx
Class.hx
Date.hx
DateTools.hx
Enum.hx
EnumValue.hx
EReg.hx
eval/
haxe/
IntIterator.hx
Lambda.hx
List.hx
Map.hx
Math.hx
Reflect.hx
Std.hx
StdTypes.hx
StringBuf.hx
String.hx
StringTools.hx
sys/
Sys.hx
Type.hx
UInt.hx
Xml.hx

Language-/target- specific libraries:

cpp/
cs/
flash/
hl/
java/
js/
lua/
neko/
php/
python/

Control Structures

var s1 = "hard string" // no string interpolation
var s2 = 'soft string' // supports string interp

// Array
var a = ["a", "b", "c"];
a.push("d");
var x = a.pop();

a.unshift("wha?"); // prepends
a.shift();         // removes from front

a.insert(1, "yo");  // shifts everything after a[1] to the right
var x = a.splice(1, 3); // remove a[1] to a[3] inclusive

var m = ["a" => 1, "b" => 2, "c" => 3];

for (x in foo) {
    trace(x);
}

for (i in 5...10) {
    trace(i); // 5 --> 9
}

for (k => v in some_map) {
    trace('$k --> $v');
}

// more to come...