|
1 | 1 | # Types |
2 | 2 |
|
3 | | -Andy C++ is currently a dynamically typed language, that means that type checks are performed at runtime. Although |
4 | | -you currently can't annotate your variables using type names they do have types at runtime. |
5 | | - |
6 | | -The type system is hierarchical with the root type being `Any`: |
7 | | - |
8 | | -* Any |
9 | | - * [Option](./types/option.md) |
10 | | - * [Boolean](./types/boolean.md) |
11 | | - * [Number](./types/number.md) |
12 | | - * Integer |
13 | | - * Int64 (64bit signed) |
14 | | - * Bigint (unlimited size) |
15 | | - * Float |
16 | | - * Complex |
17 | | - * Rational |
18 | | - * Sequence |
19 | | - * [String](./types/string.md): A mutable list of characters |
20 | | - * [List](./types/list.md): A mutable list |
21 | | - * [Tuple](./types/tuple.md): An immutable list |
22 | | - * [Unit](./types/unit.md) |
23 | | - * [Map](./types/map-and-set.md): A hashmap that associates keys with values |
24 | | - * [Deque](./types/deque.md): A double ended queue |
25 | | - * [MinHeap & MaxHeap](./types/min-max-heap.md): Min/max Heap |
26 | | - * Iterator: A type that can be consumed and produces values (Currently only used for range expressions like `5..100`) |
27 | | - * [Function](./types/function.md) |
28 | | - |
29 | | -> **Note:** `Any` is the base type for all other types. When you declare a function, its arguments default to type `Any`. |
30 | | -> Currently, the `Any` type is implicit and does not appear explicitly in the language. |
| 3 | +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. |
| 4 | + |
| 5 | +The type system is hierarchical with `Any` at the root: |
| 6 | + |
| 7 | +* `Any` |
| 8 | + * [`Option<T>`](./types/option.md) |
| 9 | + * [`Bool`](./types/boolean.md) |
| 10 | + * [`Number`](./types/number.md) |
| 11 | + * `Int` — machine `i64` or arbitrary-precision `BigInt`, picked automatically |
| 12 | + * `Float` |
| 13 | + * `Complex` |
| 14 | + * `Rational` |
| 15 | + * `Sequence<T>` |
| 16 | + * [`String`](./types/string.md): a mutable list of characters |
| 17 | + * [`List<T>`](./types/list.md): a mutable list |
| 18 | + * [`Tuple<T, ...>`](./types/tuple.md): an immutable list |
| 19 | + * [`()`](./types/unit.md): unit, the empty tuple |
| 20 | + * [`Map<K, V>`](./types/map-and-set.md): a hashmap that associates keys with values |
| 21 | + * [`Deque<T>`](./types/deque.md): a double-ended queue |
| 22 | + * [`MinHeap<T>` / `MaxHeap<T>`](./types/min-max-heap.md): min/max heap |
| 23 | + * `Iterator<T>`: produces values when consumed (currently only from range expressions like `5..100`) |
| 24 | + * [`Function`](./types/function.md) |
| 25 | + |
| 26 | +These are also the names you write in annotations. Generic types take their parameters in angle brackets: |
| 27 | + |
| 28 | +```ndc |
| 29 | +let xs: List<Int> = [1, 2, 3]; |
| 30 | +let table: Map<String, Int> = %{"a": 1, "b": 2}; |
| 31 | +let maybe: Option<Any> = Some("hi"); |
| 32 | +let pair: Tuple<Int, String> = (1, "hi"); |
| 33 | +let pair2: (Int, String) = (1, "hi"); // tuple shorthand |
| 34 | +``` |
| 35 | + |
| 36 | +Nested generics work too — the parser handles the `>>` ambiguity for you: |
| 37 | + |
| 38 | +```ndc |
| 39 | +let grid: List<List<Int>> = [[1, 2], [3, 4]]; |
| 40 | +``` |
| 41 | + |
| 42 | +> **Note:** `Any` is the base type for every other type, so an `Any`-annotated binding will accept anything. When a parameter or value has no annotation and the analyser can't infer a type, it falls back to `Any`. There is also a `Never` type used internally for things like `break` that don't produce a value — you'll rarely need to write it by hand. |
0 commit comments