Skip to content

Collections

let names: List<String> = ["Alice", "Bob", "Carol"]
let empty: List<String> = []

An empty list [] requires a type annotation whenever the element type cannot be determined from context:

let empty: List<String> = [] // OK. Annotation provides T = String
let empty = [] // error: cannot infer element type

When an empty list is passed directly to a function whose parameter type is known, the annotation can be omitted:

fn greet(names: List<String>): Void { ... }
greet([]) // OK, T inferred from the parameter type

Spread syntax combines lists:

let combined = [...list1, ...list2, "extra"]

...expr (three dots) is the spread form and only appears in list expressions. The two-dot .. is a pattern-only form for silently discarding the rest of a list or the unmentioned fields of a variant. See Pattern Matching. .. is never valid inside a list literal.

Lists can be iterated with for..in and pattern-matched with list patterns.

There is no subscript syntax (list[i]). Use get(i) for index access.

MethodSignatureReturnsNotes
size()List<T>IntNumber of elements
isEmpty()List<T>Booltrue when size is 0
get(i: Int)List<T>Option<T>None on out-of-bounds; no panic
add(item: T)List<T>List<T>Pure. Returns a new list with item appended
first()List<T>Option<T>None on empty list
last()List<T>Option<T>None on empty list
contains(item: T)List<T>BoolValue equality for primitives; reference equality for class instances
map(f: fn(T): U)List<T>List<U>Pure. Returns a new list
filter(f: fn(T): Bool)List<T>List<T>Pure. Returns a new list
fold(init: U, f: fn(U, T): U)List<T>UAccumulator-first callback convention
any(f: fn(T): Bool)List<T>BoolShort-circuits on first match; false on empty
all(f: fn(T): Bool)List<T>BoolShort-circuits on first non-match; true on empty (vacuous truth)
enumerate()List<T>List<#(Int, T)>Pairs each element with its zero-based index
reverse()List<T>List<T>Pure. Returns a new list in reversed order
prepend(item: T)List<T>List<T>Pure. Returns a new list with item at the front
concat(other: List<T>)List<T>List<T>Pure. Returns a new list with other appended
take(n: Int)List<T>List<T>Pure. Returns the first n elements; n ≤ 0 returns []
drop(n: Int)List<T>List<T>Pure. Skips the first n elements; n ≤ 0 returns a copy
unique()List<T>List<T>Pure. Removes duplicates, preserving first-occurrence order
toSet()List<T>Set<T>Converts to a Set, removing duplicates
flatten()List<List<T>>List<T>Concatenates all inner lists into a single list
join(sep: String)List<String>StringJoins all strings with sep
filterMapSome(f: fn(T): Option<U>)List<T>List<U>Applies f, keeps only Some values, discards None
filterMapOk(f: fn(T): Result<U, E>)List<T>List<U>Applies f, keeps only Ok values, discards errors
indexOf(item: T)List<T>Option<Int>Returns Some(index) of first match, or None
firstWhere(f: fn(T): Bool)List<T>Option<T>Returns Some(first element) where f is true, or None
let xs: List<Int> = [1, 2, 3, 4, 5]
let doubled = xs.map(fn(n) { n * 2 }) // (2, 4, 6, 8, 10)
let evens = xs.filter(fn(n) { n % 2 == 0 }) // (2, 4)
let sum = xs.fold(0, fn(acc, n) { acc + n }) // 15
let hasOdd = xs.any(fn(n) { n % 2 != 0 }) // true
let allPos = xs.all(fn(n) { n > 0 }) // true
// Safe index access
let assert Some(value: third) = xs.get(2) // third == 3
let missing = xs.get(99) // None
// enumerate: iterate with index
let words: List<String> = ["a", "b", "c"]
for #(i, w) in words.enumerate() {
debug i // 0, 1, 2
}
SignatureReturnsNotes
List.generate(count: Int, f: fn(Int): T)List<T>Calls f with each zero-based index 0..count-1. count ≤ 0 returns [].
List.filled(count: Int, value: T)List<T>Creates count copies of value. count ≤ 0 returns []. Note: all entries reference the same object. Use List.generate for independent instances.
// Unique items using the index:
let squares: List<Int> = List.generate(5, fn(i: Int): Int { i * i })
// squares == (0, 1, 4, 9, 16)
// Repeated sentinel value:
let zeros: List<Int> = List.filled(4, 0)
// zeros == (0, 0, 0, 0)

let scores: Map<String, Int> = {"Alice": 95, "Bob": 87}
let empty: Map<String, Int> = Map.empty()

There is no subscript syntax (map["key"]). Use get(key) for key access, which returns Option<V>.

MethodReceiverReturnsNotes
size()Map<K,V>IntNumber of key-value pairs
isEmpty()Map<K,V>Booltrue when the map has zero entries
containsKey(key: K)Map<K,V>Booltrue if the key exists
get(key: K)Map<K,V>Option<V>Some(value) if found, None otherwise
put(key: K, value: V)Map<K,V>Map<K,V>Pure. Returns a new map with the key set
remove(key: K)Map<K,V>Map<K,V>Pure. Returns a new map without the key
keys()Map<K,V>List<K>All keys as a list
values()Map<K,V>List<V>All values as a list
entries()Map<K,V>List<#(K, V)>Key-value pairs as a list of tuples

Map.empty(). Creates an empty map. A type annotation is required:

let m: Map<String, Int> = Map.empty()

Map.fromList(list: List<#(K, V)>): Map<K, V>. Constructs a map from a list of key-value tuple pairs. If the list contains duplicate keys, the last entry wins.

let m: Map<String, Int> = Map.fromList([#("a", 1), #("b", 2)])
// Round-trip with entries():
let original: Map<String, Int> = {"x": 10, "y": 20}
let copy: Map<String, Int> = Map.fromList(original.entries())
for k in scores.keys() {
debug k
}
for #(key, value) in scores.entries() {
debug "${key}: ${value}"
}

let tags: Set<String> = #{"apex", "salesforce"}

Sets are immutable; all mutating methods return a new Set<T>.

MethodReceiverReturnsDescription
size()Set<T>IntNumber of elements
isEmpty()Set<T>Booltrue if the set has no elements
contains(item: T)Set<T>Booltrue if item is in the set
add(item: T)Set<T>Set<T>New set with item included
remove(item: T)Set<T>Set<T>New set with item excluded
toList()Set<T>List<T>Converts to a list (order unspecified)
map(f: fn(T): U)Set<T>Set<U>Transforms each element with f
filter(f: fn(T): Bool)Set<T>Set<T>Keeps elements for which f returns true
union(other: Set<T>)Set<T>Set<T>All elements from both sets
intersection(other: Set<T>)Set<T>Set<T>Elements present in both sets
difference(other: Set<T>)Set<T>Set<T>Elements in receiver but not in other
let nums: Set<Int> = #{1, 2, 3}
debug nums.size() // 3
debug nums.contains(2) // true
let s2 = nums.add(4)
debug s2.size() // 4
let evens = nums.filter(fn(x: Int): Bool { x % 2 == 0 })
debug evens.size() // 1
let u = #{1, 2}.union(#{2, 3, 4})
debug u.size() // 4
let inter = #{1, 2, 3}.intersection(#{2, 3, 4})
debug inter.size() // 2
let diff = #{1, 2, 3}.difference(#{2, 3})
debug diff.size() // 1