Collection Types
This section covers the standard collection abstractions used throughout Nex code. Array, Map, Set, and Min_Heap[T] are built-in collection types. Stack[T] is a common generic collection class pattern built on top of Array[T].
All built-in collection types inherit Any. Their to_string, equals, and clone methods operate recursively: to_string renders nested structure, equals performs deep structural equality, and clone performs a deep copy.
Set membership and dedup, and Map key lookup, compare by Nex value equality — the same equals/hash used by the = operator — so a class that overrides equals/hash is matched by value as an element or key.
Each method table below includes a Complexity column, given as time / space (average case for Map/Set, as with any hash table). nex file.nex compiles to JVM bytecode; a tree-walking interpreter is used as a fallback and an easy to understand reference implementation. The two backends agree on every operation's complexity except Map.remove and Set.remove: O(1) average on the compiled backend (backed by a real hash table), O(n) on the interpreter (which keeps a separate insertion-order list that removal must also filter).
Array
Construction
[]
create Array.filled(3, 0)
create Array[String].filled(2, "x")
[]creates an empty array literal.create Array.filled(size, value)creates a new array of lengthsizewhere each element is initialized tovalue.sizemust be a non-negativeInteger.- The element type is inferred from
value, or checked againstArray[T]when the target array type is declared explicitly.
Methods
| Method | Arguments | Returns | Description | Complexity |
|---|---|---|---|---|
get |
index: Integer |
Any |
Read element at index. |
O(1) / O(1) |
add |
value: Any |
Void |
Append value. | O(1) amortized / O(1) |
add_at |
index: Integer, value: Any |
Void |
Insert value at index. | O(n) / O(1) |
length |
none | Integer |
Number of elements. | O(1) / O(1) |
is_empty |
none | Boolean |
True when array has no elements. | O(1) / O(1) |
contains |
elem: Any |
Boolean |
Membership test. | O(n) / O(1) |
index_of |
elem: Any |
Integer |
First index or -1 if not found. |
O(n) / O(1) |
remove |
index: Integer |
Void |
Remove element at index. | O(n) / O(1) |
reverse |
none | Array[Any] |
Return reversed array. | O(n) / O(n) |
set |
index: Integer, value: Any |
Void |
Replace element at index. | O(1) / O(1) |
sort |
none | Array[Any] |
Return a new array sorted by built-in order or Comparable.compare. |
O(n log n) / O(n) |
sort |
compareFn: Function(a: Any, b: Any): Integer |
Array[Any] |
Return a new array sorted using compareFn(a, b) -> Integer. |
O(n log n) / O(n) |
slice |
start: Integer, end: Integer |
Array[T] |
Subrange [start, end). Negative indices count from the end: -1 is one before the last element. Out-of-bounds values are clamped. |
O(n) / O(n) |
take |
n: Integer |
Array[T] |
First n elements. Returns the whole array if n ≥ length, empty if n ≤ 0. |
O(n) / O(n) |
drop |
n: Integer |
Array[T] |
All elements after the first n. Returns empty if n ≥ length, the whole array if n ≤ 0. |
O(n) / O(n) |
take_last |
n: Integer |
Array[T] |
Last n elements. Returns the whole array if n ≥ length, empty if n ≤ 0. |
O(n) / O(n) |
drop_last |
n: Integer |
Array[T] |
All elements except the last n. Returns empty if n ≥ length, the whole array if n ≤ 0. |
O(n) / O(n) |
concat |
other: Array[T] |
Array[T] |
Return a new array containing this array followed by other. |
O(n + m) / O(n + m) |
to_string |
none | String |
Render the array and its nested values as text. | O(n) / O(n), deep* |
equals |
other: Any |
Boolean |
Deep structural equality. | O(n) / O(1), deep* |
clone |
none | Array[T] |
Deep-copy the array and its nested values while preserving element type. | O(n) / O(n), deep* |
cursor |
none | ArrayCursor |
Create iterator. | O(1) / O(1) to create |
* "Deep" means the cost scales with the array's total nested size, not just its element count, since these recurse into any nested Array/Map/Set/object elements.
sort()requires elements to be built-in sortable scalars orComparable.sort(compareFn)uses the provided comparator function instead. The comparator must return anInteger: negative whena < b, positive whena > b,0when equal.
Map
Construction
{}
Methods
| Method | Arguments | Returns | Description | Complexity |
|---|---|---|---|---|
get |
key: Any |
Any |
Read value for key (fails if key missing). | O(1) avg / O(1) |
try_get |
key: Any, default: Any |
Any |
Read value or default if missing. | O(1) avg / O(1) |
set |
key: Any, value: Any |
Void |
Add/replace key-value entry. | O(1) avg / O(1) |
put |
key: Any, value: Any |
Void |
Alias for set. |
O(1) avg / O(1) |
size |
none | Integer |
Number of entries. | O(1) / O(1) |
is_empty |
none | Boolean |
True when map has no entries. | O(1) / O(1) |
contains_key |
key: Any |
Boolean |
Key existence test. | O(1) avg / O(1) |
keys |
none | Array[Any] |
Array of keys. | O(n) / O(n) |
values |
none | Array[Any] |
Array of values. | O(n) / O(n) |
remove |
key: Any |
Void |
Delete entry by key. | O(1) avg / O(1)† |
to_string |
none | String |
Render the map and its nested values as text. | O(n) / O(n), deep* |
equals |
other: Any |
Boolean |
Deep structural equality. | O(n) / O(1), deep* |
clone |
none | Map[K, V] |
Deep-copy the map and its nested keys and values while preserving key/value types. | O(n) / O(n), deep* |
cursor |
none | MapCursor |
Create entry iterator. | O(n) / O(n) to create†, then O(1) / O(1) per step |
* "Deep" means the cost scales with the total nested size of keys/values, not just entry count.
† remove and cursor are the two operations where the backends diverge: remove is O(1) average on the compiled backend but O(n) on the interpreter (see the note above); cursor creation is O(n) on both, since it snapshots every key up front rather than iterating lazily.
Set
Construction
#{}
create Set[Integer].from_array([1, 2, 3])
Set literals use #{...}. The empty map literal remains {}.
Methods
| Method | Arguments | Returns | Description | Complexity |
|---|---|---|---|---|
contains |
value: T |
Boolean |
Membership test. | O(1) avg / O(1) |
add |
value: T |
Void |
Add a value in place. A duplicate (by value equality) is a no-op. | O(1) avg / O(1) |
remove |
value: T |
Void |
Remove the element equal to value in place, if present. |
O(1) avg / O(1)† |
union |
other: Set[T] |
Set[T] |
Set union. | O(n + m) avg / O(n + m) |
difference |
other: Set[T] |
Set[T] |
Elements in this set but not in other. |
O(n) avg / O(n) |
intersection |
other: Set[T] |
Set[T] |
Common elements. | O(n) avg / O(n) |
symmetric_difference |
other: Set[T] |
Set[T] |
Elements in exactly one of the two sets. | O(n + m) avg / O(n + m) |
size |
none | Integer |
Number of elements. | O(1) / O(1) |
is_empty |
none | Boolean |
True when the set has no elements. | O(1) / O(1) |
to_array |
none | Array[T] |
Copy the set's elements into a new array, in insertion order. | O(n) / O(n) |
to_string |
none | String |
Render the set and its nested values as text. | O(n) / O(n), deep* |
equals |
other: Any |
Boolean |
Deep structural equality. | O(n) / O(1), deep* |
clone |
none | Set[T] |
Deep-copy the set and its nested values while preserving element type. | O(n) / O(n), deep* |
cursor |
none | SetCursor |
Create iterator. | O(n) / O(n) to create†, then O(1) / O(1) per step |
* "Deep" means the cost scales with the total nested size of elements, not just element count.
† remove and cursor are the two operations where the backends diverge, the same way as Map above: remove is O(1) average on the compiled backend but O(n) on the interpreter; cursor creation is O(n) on both, since it snapshots every element up front. (n above is the size of the receiver, m the size of other.)
Min_Heap[T]
Construction
create Min_Heap.empty
create Min_Heap[Integer].empty
create Min_Heap[Box].from_comparator(compare_boxes)
create Min_Heap.emptycreates an empty heap that uses natural ordering.empty()is intended for element types that already support ordering: built-in sortable scalars or classes implementingComparable.- For non-
Comparableelement types, usefrom_comparator(...). from_comparator(compare)expects aFunction(a: T, b: T): Integercomparator: negative when the first value is smaller, positive when larger,0when equal.
Methods
| Method | Arguments | Returns | Description | Complexity |
|---|---|---|---|---|
insert |
value: T |
Void |
Insert a value into the heap. | O(log n) / O(1) |
extract_min |
none | T |
Remove and return the smallest value. Fails if empty. | O(log n) / O(1) |
try_extract_min |
none | ?T |
Remove and return the smallest value, or nil if empty. |
O(log n) / O(1) |
peek |
none | T |
Return the smallest value without removing it. Fails if empty. | O(1) / O(1) |
try_peek |
none | ?T |
Return the smallest value, or nil if empty. |
O(1) / O(1) |
size |
none | Integer |
Number of stored elements. | O(1) / O(1) |
is_empty |
none | Boolean |
True when the heap has no elements. | O(1) / O(1) |
Same binary-heap algorithm on both backends — no divergence.
Example
let failure: Min_Heap[Integer] := create Min_Heap.empty
failure.insert(0)
failure.insert(3)
failure.insert(1)
print(failure.peek) -- 0
print(failure.extract_min) -- 0
print(failure.try_extract_min) -- 1
print(failure.try_extract_min) -- 3
print(failure.try_extract_min) -- nil
Stack[T]
Stack[T] is a generic last-in, first-out collection abstraction. It is not a built-in primitive type; it is typically defined as a class using Array[T] for storage.
Typical Definition
class Stack [T]
create
make() do
items := []
end
feature
items: Array[T]
push(value: T) do
items.add(value)
end
pop(): T do
result := items.get(items.length - 1)
items.remove(items.length - 1)
end
peek(): T do
result := items.get(items.length - 1)
end
is_empty(): Boolean do
result := items.is_empty
end
size(): Integer do
result := items.length
end
end
Methods
| Method | Arguments | Returns | Description | Complexity |
|---|---|---|---|---|
push |
value: T |
Void |
Push value onto the top of the stack. | O(1) amortized / O(1) |
pop |
none | T |
Remove and return the top element. | O(1) / O(1) |
peek |
none | T |
Return the top element without removing it. | O(1) / O(1) |
is_empty |
none | Boolean |
True when the stack has no elements. | O(1) / O(1) |
size |
none | Integer |
Number of stored elements. | O(1) / O(1) |
pop/peek are O(1), not O(n), because they always touch the array's last index, which never shifts — unlike Array.remove at an arbitrary index.
Notes
popandpeekusually require the stack to be non-empty.- A contract-based version should add preconditions for these operations.
Stack[T]is the canonical example of a user-defined generic collection in Nex.
Examples
let xs: Array [Integer] := [10, 20]
xs.add(30)
xs.add_at(1, 15) -- [10, 15, 20, 30]
print(xs.get(2)) -- 20
print(xs.index_of(30)) -- 3
let m: Map [String, String] := {"lang": "Nex"}
m.set("kind", "language")
print(m.get("lang")) -- "Nex"
print(m.try_get("missing", "n/a")) -- "n/a"
print(m.contains_key("kind")) -- true
let s1 := #{1, 2}
let s2 := #{2, 3}
print(s1.union(s2)) -- #{1, 2, 3}
let stack := create Stack[Integer].make
stack.push(10)
stack.push(20)
print(stack.peek) -- 20