Collections & Iterators
The methods of each type are in the generated reference: Array, Dict, Tuple and Iterator. Arrays, dicts and class instances are shared on assignment; see Values & Sharing.
| Type | Literal | Size | Mutable | Elements |
|---|---|---|---|---|
| Array | #[a, b, c] | Grows and shrinks | Yes | Any, mixed |
| Dict | #{key: value, …} | Grows and shrinks | Yes | String or Number keys, any values |
| Tuple | (a, b, …) | Fixed, at least 2 | No | Any, mixed |
Trailing commas are allowed in all three literals, and all three nest.
Arrays
Section titled “Arrays”let nums = #[1, 2, 3, 4, 5];assert nums[0] == 1; // zero-basedassert nums.get(4) == 5; // same as indexingnums[0] = 10; // index assignmentnums.push(6); // push and pop mutate in placeassert nums.pop() == 6;let matrix = #[#[1, 2], #[3, 4]];assert matrix[1][0] == 3;print(nums);.push() and .pop() change the array; every other method returns a new value. An array is played
as a pattern with Sequence(array).
Keys are Strings or Numbers, and the two are distinct: 200 and "200" are different keys. A dict
has no order — .keys(), .values() and .entries() return entries in any order.
let cc = #{"cutoff": 74, "reso": 71, 7: "volume"};assert cc["cutoff"] == 74; // a missing key is an errorassert cc.get("drive") == NUL; // .get returns NUL insteadcc["cutoff"] = 20; // index assignment adds or replacescc["cutoff"] += 1;cc.set("drive", 0.3);assert cc.remove("reso") == 71; // .remove returns the removed valueassert cc.contains_key(7);print(cc);.merge(other) returns a new dict in which other’s keys win. The dict callbacks of .map(),
.filter() and .reduce() receive the key and the value: fn(k, v), fn(acc, k, v).
Tuples
Section titled “Tuples”A tuple is a fixed group of two or more values; (1) is a parenthesised expression, not a tuple.
It cannot be changed. Index it with t[i]; compare it with == and !=, element by element
(tuples of different lengths are never equal). Unpack it with a
destructuring let or a
match tuple pattern.
let point = (3, 4);let mixed = (1, "hello", C4);assert mixed[2] == C4;assert mixed.length() == 3;assert (1, 2) == (1, 2);assert (1, 2) != (1, 2, 3);let box = ((0, 0), (640, 480));assert box[1][0] == 640;print(point);A DSP block’s stereo return (out_l, out_r) is a tuple.
Iterators
Section titled “Iterators”An iterator is a lazy, single-use sequence. Get one with .iter():
| Source | Yields | Ends |
|---|---|---|
| Array, Tuple | Each element | After the last |
| String | Each character, as a one-character String | After the last |
| Dict | Each key, in unspecified order | After the last |
| Pattern | Each event, one per step | Never |
The Iterator reference groups its methods:
- Advancing and transforming methods (
take,skip,step_by,enumerate,map,filter,zip,chain) return a new iterator and do no work yet.enumerateandzipyield[a, b]arrays;zipstops when either side ends. - Consuming methods (
next,collect,count,first,last,find,any,all,fold,flatten) pull values through and return a result.next()returnsNULonce the iterator is exhausted.
let it = #[10, 20].iter();assert it.next() == 10;assert it.next() == 20;assert it.next() == NUL; // exhausted, and stays exhausted
let evens = #[1, 2, 3, 4, 5, 6].iter() .filter(fn(x) { return x % 2 == 0; }) // lazy .map(fn(x) { return x * 10; }) // lazy .collect(); // runs the pipelineprint(evens); // [20, 40, 60]
let notes = [C4 E4 G4].iter().take(3).map(fn(e) { return e.note(); }).collect();print(notes); // [60, 64, 67]A pattern iterator never ends, so a consuming method on it without .take(n) first never returns:
[C4 D4 E4].iter().collect(); // runs foreverArray .map() and .filter() return arrays; the same methods on an iterator return iterators.
for … in accepts an iterator directly.