Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Map and Set

A map holds values by key, a set unique values. Unlike an object, whose keys are strings, their keys may be any hashable value; like an object, they keep keys in the order they were first added.

let mut stock = map();
stock["apple"] = 3;
stock["pear"] = 0;
print(stock["apple"]);   // 3
print(stock);            // map {"apple": 3, "pear": 0}

let mut visitors = set();
visitors.add("ann");
visitors.add("bob");
visitors.add("ann");
print(visitors);         // set {"ann", "bob"}
print(visitors.len());   // 2

Making one

map() makes an empty map and map(src) one from an object, a struct, another map or an array of [key, value] pairs; set() and set(array) likewise.

print(map({ host: "localhost", port: 8080 }));  // map {"host": "localhost", "port": 8080}
print(map([[200, "OK"], [404, "Not Found"]]));  // map {200: "OK", 404: "Not Found"}
print(set(["a", "b", "a"]));                    // set {"a", "b"}

Keys

A key is any hashable value: nil, a boolean, a number (1 and 1.0 are one key; NaN is none), a string, bytes, a function, a struct type, or a struct whose fields are hashable, compared by value. A struct makes a natural composite key:

struct Pos { x, y }

let mut grid = map();
grid[Pos { x: 0, y: 1 }] = "wall";
print(grid[Pos { x: 0, y: 1 }]);                // wall
print(grid.get(Pos { x: 9, y: 9 }, "floor"));   // floor

An array, object, map or set is not hashable, as it can change:

let mut seen = map();
seen[[1, 2]] = true; // TypeError: Cannot use an array as a key.

Reading and writing

m[k] reads a key and a missing one is a KeyError; m?.[k] gives nil instead. m[k] = v sets one, like an array element, so m must be mutable.

let mut prices = map({ apple: 1.5 });
print(prices?.["kiwi"]); // nil
print(prices["kiwi"]);   // KeyError: Key not found: "kiwi".

Map methods: get(k[, default]), set(k, v), has(k), delete(k) (whether it was there), clear(), and keys(), values(), entries(), new arrays. Like an array’s in-place methods, set and clear return nil.

let mut stock = map();
stock.set("apple", 3);
stock.set("pear", 0);
stock.set("plum", 7);

print(stock.get("kiwi"));     // nil
print(stock.get("kiwi", 0));  // 0
print(stock.has("pear"));     // true
print(stock.delete("pear"));  // true
print(stock.delete("pear"));  // false
print(stock.keys());          // ["apple", "plum"]
print(stock.values());        // [3, 7]
print(stock.entries());       // [["apple", 3], ["plum", 7]]

A set has add(x), contains(x), delete, clear, values(), and union(s), intersection(s), difference(s), new sets. As everywhere, has tests a key (of an object or a map) and contains a value (of an array, a string or a set).

let backend = set(["ann", "bob", "eve"]);
let frontend = set(["bob", "kim"]);

print(backend.contains("eve"));          // true
print(backend.union(frontend));          // set {"ann", "bob", "eve", "kim"}
print(backend.intersection(frontend));   // set {"bob"}
print(backend.difference(frontend));     // set {"ann", "eve"}

Iterating

m.len() counts the entries; for k, v in m walks a map’s keys and values, for k in m its keys, and for x in s or for i, x in s a set, always in insertion order.

let stock = map({ apple: 3, plum: 7 });
for name, n in stock {
    print("{name}: {n}");
}
// apple: 3
// plum: 7

A loop may set existing keys and delete them, but adding one is a ValueError; walk m.keys() to change it freely.

let mut counts = map({ a: 1 });
for k in counts {
    counts[k + "!"] = 0; // ValueError: Cannot add to a map while iterating over it.
}
let mut counts = map({ a: 1, b: 2 });
for k in counts.keys() {
    counts[k + "!"] = 0;
}
print(counts); // map {"a": 1, "b": 2, "a!": 0, "b!": 0}

Equality and conversion

== compares entries in any order. [...s] spreads a set into an array; json.stringify writes a set as an array and a map of string keys as an object, in order. Both are references, like arrays.

print(map({ a: 1, b: 2 }) == map({ b: 2, a: 1 })); // true

let ids = set([3, 1, 2]);
print([...ids]);                      // [3, 1, 2]
print(json.stringify(ids));           // [3,1,2]
print(json.stringify(map({ a: 1 }))); // {"a":1}