6 Language Features

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.

Extern classes:

Externs can be used to describe target-specific interaction in a type-safe manner.

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 & 1 == 0) i];

Map Comprehension:

Create and populate maps quickly using for loops and logic.

var primality = [for (i in 0...100) i => isPrime(i)];

Classes, interfaces and inheritance:

AIR SPEED 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.Browser.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 AIR SPEED Language. Furthermore, AIR SPEED 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 designated 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 AIR SPEED 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 AIR SPEED 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(air speed.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 air speed.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;
}

Access control:

The access control language feature uses the AIR SPEED metadata syntax to force or allow access classes or fields.

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) {}
}