Types
Andy C++ runs as a dynamically typed language — values carry their types at runtime and most checking happens then. You can also attach type annotations to variables, function parameters, and return values, and the analyser will use them to flag obvious mismatches before the program runs.
The type system is hierarchical with Any at the root:
AnyOption<T>BoolNumberInt— machinei64or arbitrary-precisionBigInt, picked automaticallyFloatComplexRational
Sequence<T>String: a mutable list of charactersList<T>: a mutable listTuple<T, ...>: an immutable list(): unit, the empty tuple
Map<K, V>: a hashmap that associates keys with valuesDeque<T>: a double-ended queueMinHeap<T>/MaxHeap<T>: min/max heapIterator<T>: produces values when consumed (currently only from range expressions like5..100)
Function
These are also the names you write in annotations. Generic types take their parameters in angle brackets:
let xs: List<Int> = [1, 2, 3];
let table: Map<String, Int> = %{"a": 1, "b": 2};
let maybe: Option<Any> = Some("hi");
let pair: Tuple<Int, String> = (1, "hi");
let pair2: (Int, String) = (1, "hi"); // tuple shorthand
Nested generics work too — the parser handles the >> ambiguity for you:
let grid: List<List<Int>> = [[1, 2], [3, 4]];
Note:
Anyis the base type for every other type, so anAny-annotated binding will accept anything. When a parameter or value has no annotation and the analyser can’t infer a type, it falls back toAny. There is also aNevertype used internally for things likebreakthat don’t produce a value — you’ll rarely need to write it by hand.