Abstract types: An abstract type is a compile-time construct which is represented in a different way at runtime. This allows giving a whole new meaning to existing types.
Anonymous structures: Data can easily be grouped in anonymous structures, minimizing the necessity of small data classes.
var point = { x: 0, y: 10 }; point.x += 10;
Array Comprehension: Create and populate arrays quickly using for loops and logic.
var evenNumbers = [ for (i in 0...100) if (i%2==0) i ];
Classes, interfaces and inheritance: Haxe allows structuring code in classes, making it an object-oriented language. Common related features known from languages such as Java are supported, including inheritance and interfaces.
Conditional compilation: Conditional Compilation allows compiling specific code depending on compilation parameters. This is instrumental for abstracting target-specific differences, but can also be used for other purposes, such as more detailed debugging.
#if js js.Lib.alert("Hello"); #elseif sys Sys.println("Hello"); #end
(Generalized) Algebraic Data Types: Structure can be expressed through algebraic data types (ADT), which are known as enums in the Haxe Language. Furthermore, Haxe supports their generalized variant known as GADT.
enum Result { Success(data:Array<Int>); UserError(msg:String); SystemError(msg:String, position:PosInfos); }
Inlined calls: Functions can be designed as being inline, allowing their code to be inserted at call-site. This can yield significant performance benefits without resorting to code duplication via manual inlining.
Iterators: Iterating over a set of values, e.g. the elements of an array, is very easy in Haxe courtesy of iterators. Custom classes can quickly implement iterator functionality to allow iteration.
for (i in [1, 2, 3]) { trace(i); }
Local functions and closures: Functions in Haxe are not limited to class fields and can be declared in expressions as well, allowing powerful closures.
var buffer = ""; function append(s:String) { buffer += s; } append("foo"); append("bar"); trace(buffer); // foobar
Metadata: Add metadata to fields, classes or expressions. This can communicate information to the compiler, macros, or runtime classes.
class MyClass { @range(1, 8) var value:Int; } trace(haxe.rtti.Meta.getFields(MyClass).value.range); // [1,8]
Static Extensions: Existing classes and other types can be augmented with additional functionality through using
static extensions.
using StringTools; " Me & You ".trim().htmlEscape();
String Interpolation: Strings declared with a single quotes are able to access variables in the current context.
trace('My name is $name and I work in ${job.industry}');
Partial function application: Any function can be applied partially, providing the values of some arguments and leaving the rest to be filled in later.
var map = new haxe.ds.IntMap(); var setToTwelve = map.set.bind(_, 12); setToTwelve(1); setToTwelve(2);
Pattern Matching: Complex structures can be matched against patterns, extracting information from an enum or a structure and defining specific operations for specific value combination.
var a = { foo: 12 }; switch (a) { case { foo: i }: trace(i); default: }
Properties: Variable class fields can be designed as properties with custom read and write access, allowing fine grained access control.
public var color(get,set); function get_color() { return element.style.backgroundColor; } function set_color(c:String) { trace('Setting background of element to $c'); return element.style.backgroundColor = c; }
Type Parameters, Constraints and Variance: Types can be parametrized with type parameters, allowing typed containers and other complex data structures. Type parameters can also be constrained to certain types and respect variance rules.
class Main<A> { static function main() { new Main<String>("foo"); new Main(12); // use type inference } function new(a:A) { } }