Select a collection based on the behavior your application must preserve: positional order with duplicates, key-based lookup, or element uniqueness. Comprehensions provide a concise syntax to filter and transform these collections while preserving their ordering rules.
Choose the collection first
| Collection | Choose it for | Observable behavior |
|---|---|---|
Array<T> | Ordered items, positional access, and repeated values | Iterates by increasing index and preserves duplicate values |
Map<K, V> | Values selected by key | Keys maintain insertion order; updating an existing key preserves its slot |
Set<T> | Unique values | The first matching value preserves the insertion slot |
Run one example
Save this as collections-comprehensions.tpz:
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)topaz check collections-comprehensions.tpz
topaz run collections-comprehensions.tpzIt prints:
[10, 25, 10]:[10, 25]:[Ada, Lin]
[50]:10:true
missingThe array retains both 10 values. The set deduplicates the second 10 and preserves the initial insertion order. Because labels.keys returns an array ordered by insertion, membership checks are written as "Ada" in labels.keys.
Read and change collections deliberately
scores[0] performs a direct indexed read. Passing a negative or out-of-range index triggers a runtime fault. scores.get(9) avoids runtime faults by returning an Option, which the example handles using match.
In-place mutation requires a mutable root binding. Declare let mut values = [...] before invoking a mutating operation such as values.push(...). Conversely, a non-mutating expression can derive a new collection from an immutable binding.
Map duplicate handling differs from Set handling. Defining duplicate literal keys produces a static error. If two keys evaluate to equal values at runtime, map construction evaluates the operands and raises a fault rather than overwriting. Map.insert serves as the explicit operation for inserting or updating key-value pairs.
Literal, loop, or comprehension?
- Use
[a, b],set { a, b }, ormap { key: value }when elements are specified directly as literals. - Use
for item in source { ... }when expressing the logic as explicit sequential steps improves readability. In statement position, it executes side effects. In expression position, it collects body evaluation results into anArray. - Use
[ for item in source if condition => result ]when filtering and transformation fit naturally into a single expression. Replace the outer brackets withset { ... }for unique set elements ormap { ... }for key-value entries.
Comprehension clauses start with for, continue with subsequent for or if keywords without commas, and conclude with =>. Clauses nest sequentially from left to right. The resulting collection is constructed only after every evaluated clause and body expression succeeds.
Common mistakes
The collection types are Array<T>, Map<K, V>, and Set<T>. [T] is not a valid collection type syntax. Set and map literals require explicit set and map keywords. #{...} and bare {key: value} syntax are invalid.
key in map is invalid. Use key in map.keys instead. A refutable pattern mismatch inside a comprehension causes a runtime fault rather than filtering items automatically. Write an explicit if clause to skip non-matching elements.
Exact boundaries
- Array spread operations accept only another
Array. Set and map literals and comprehensions do not support spread syntax. - Empty
set {}andmap {}literals require explicit type context forSet<T>orMap<K, V>. - Map keys and set elements must be recursively keyable.
- Removing an entry removes its insertion slot. Reinserting the entry appends it to the end. Updating an existing map value preserves key order.
forloops iterate overArray, integer ranges,Set, andmap.keys. Iterating over strings requires explicit scalar operations.
User-defined iteration, generators, lazy or parallel comprehensions, iterable spread, and unordered collection semantics are not supported in the current language specification.
Return to the course example in Data and Control. Refer to Patterns & Control Flow for comprehension bindings, and consult Collection Operations for available standard methods.