Data & Control

Collections & Comprehensions

Choose Array, Map, or Set by order, lookup, and duplicates, then filter and transform their values.

Choose Array, Map, or Set to keep ordered values, look up keys, or remove duplicates. Use a comprehension to filter those values and build a new collection.

Install Topaz using First Program. The Data and Control lesson introduces arrays and loops.

Filter scores and read a missing position

Save this code as collections-comprehensions.tpz in your working folder.

TOPAZ
let scores = [10, 25, 10]
let labels = map { "Ada": 10, "Lin": 25 }
let unique = set { 10, 25, 10 }
let focused = [ for score in scores if score >= 20 => score * 2 ]

let first = scores[0]
let missing = scores.get(9)
let hasAda = "Ada" in labels.keys
let missingLabel = match missing {
    case Some(value) => "found {value}"
    case None => "missing"
}

print("{scores}:{unique.toArray()}:{labels.keys}")
print("{focused}:{first}:{hasAda}")
print(missingLabel)

In that folder, check the file and run it.

BASH
topaz check collections-comprehensions.tpz
topaz run collections-comprehensions.tpz

The check succeeds with exit code 0. The program prints these results.

Output
[10, 25, 10]:[10, 25]:[Ada, Lin]
[50]:10:true
missing

Follow the input to the result

The array keeps [10, 25, 10]. The set keeps [10, 25] in first-insertion order. The map associates "Ada" with 10 and "Lin" with 25. Its keys array keeps that insertion order.

The expression assigned to focused is a comprehension. It visits each score, keeps values at least 20, and doubles them. From this input, 25 passes the condition and becomes 50, so the result is [50].

NeedChooseOrder and duplicates
Read values by positionArray<T>Increasing index order, with duplicates preserved
Read values by keyMap<K, V>Insertion order of keys
Keep distinct valuesSet<T>First insertion of each distinct value

Read or change a collection

scores[0] reads 10. Direct indexing faults for a negative or out-of-range index. Use scores.get(9) when a position may be missing. It returns None, so the example prints missing. A successful get returns Some(value). These two cases form Option.

To change a collection in place, declare its root binding with let mut before calling a mutator such as push. An immutable binding can still supply input to an expression that creates a new collection.

Map construction rejects duplicate keys. A repeated literal key is a static error. Keys that become equal during execution cause a fault after all source operands succeed. Use insert to add a key or update its value deliberately.

Updating an existing map value preserves key order. Removing a map entry or set element removes its position. Reinserting it puts it at the end.

Choose a literal, loop, or comprehension

  • Write items directly with [a, b], set { a, b }, or map { key: value }.
  • Use for item in source { ... } for several steps. As a statement, it performs actions such as printing. As an expression, it collects body results in an Array.
  • Use [ for item in source if condition => result ] for filtering and transformation. For a set, use set { for item in source => result }. For a map, use map { for item in source => key: value }.

A comprehension starts with for. Add further for or if clauses without commas, then write => and the result. Clauses nest from left to right. The collection becomes available after all evaluated clauses and body expressions succeed.

Correct a lookup or literal

To test map keys, use "Ada" in labels.keys. The form "Ada" in labels is invalid.

Use Array<T> for an array type, not [T]. Start a set with set and a map with map. { key: value } creates a structural record. It does not create a map. The form #{...} is invalid.

In collections-comprehensions.tpz, replacing scores.get(9) with scores[9] stops execution with an out-of-range fault. Keep get when missing input is expected, or correct the index before using direct access.

A comprehension pattern must match each item it reaches. A mismatch faults. Filter unwanted items with an if clause before a later pattern tries to extract their parts.

Other collection rules

  • Array spread accepts another Array. Set and map literals and comprehensions have no spread form.
  • Empty set {} and map {} need an expected Set<T> or Map<K, V> type.
  • Map keys and set elements must support key comparison. For compound values, every contained part must also support it. This property is called keyability.
  • for visits arrays, integer ranges, sets, and map.keys in their defined order. For a string, use scalar operations to obtain its Unicode scalar values.
  • User-defined iteration, generators, lazy or parallel comprehensions, general iterable spread, and unordered collections are not supported.

See Patterns & Control Flow for binding values during iteration. Collection Operations lists the available methods.