Maps

A map is an unordered collection of key/value pairs.

Map literals

Literal keys must be bare identifiers. { name: "Alice" } works; { "first-name": "Alice" } is a syntax error, because the parser only accepts an identifier token before the colon in a map literal. To use a key that isn't a valid identifier (spaces, hyphens, starts with a digit, etc.), build the map with {} and set the key via bracket indexing instead.
let user = { name: "Alice", age: 30 };
let empty = {};
empty["not-an-identifier"] = true; // fine via bracket indexing

Reading and writing values

Bracket indexing works with any key type (string, number, boolean...), not just identifier-style strings:

let m = {};
m[1] = "one";
m["two"] = 2;
output(m[1]);      // "one"
output(m["two"]);  // 2
output(m["missing"]); // null -unlike arrays, an unknown key returns null instead of erroring

Dot access doubles as key access

For a key that is a valid identifier, map.key and map["key"] are interchangeable -both for reading and for writing a new key:

let user = { name: "Alice" };
output(user.name);      // "Alice" -same as user["name"]
user.email = "a@example.com"; // adds a new key, same as user["email"] = ...
output(user.doesNotExist); // null -reading an unknown property/key never errors on a map

This is different from a struct, where accessing an undeclared field or method with dot syntax raises a runtime error instead of returning null.

size

output({ a: 1, b: 2 }.size); // 2 -a property, not a method

Iteration

foreach over a map yields its values, not key/value pairs:

let scores = { alice: 90, bob: 75 };
foreach (v: scores) { output(v); } // 90, 75

To get both, iterate the keys and index back in:

foreach (k: scores.keys()) {
    output(k + ": " + scores[k]);
}

Methods

keys() → array

All keys, as an array, in insertion order.

values() → array

All values, as an array, in the same order as keys().

entries() → array -see warning

This does not currently return [key, value] pairs as its name implies. Verified against the interpreter: it returns [key, positionalIndex] pairs instead -the value in each pair is the key's 0-based position, not the actual value stored at that key.

let m = { a: 10, b: 20, c: 30 };
output(m.entries());
// [["a",0],["b",1],["c",2]]  -NOT [["a",10],["b",20],["c",30]]

Until this is fixed upstream, use keys() together with indexing (as shown above) instead of relying on entries() for actual key/value pairs.

contains(key) → boolean

Whether key exists in the map.

isEmpty() → boolean

Whether the map has zero entries.

remove(key) mutates

Removes key (and its value). Returns the map itself. Raises E1034 if key doesn't exist -see E1033 too if you're using an array or map itself as a key, which only fails cleanly through this method.

clear() mutates

Empties the map in place. Returns null.

copy() → map

Returns a new map with the same entries. Assigning a map to another variable does not copy it.

How maps print

output({ a: 1, b: "x" }); // {"a": 1, "b": "x"}