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. Map_Entry[K, V] is the pair type a Map yields when iterated. Stack[T] is a common generic collection class pattern built on top of Array[T].

In the tables below, T is the element type of an Array[T] or Set[T], and K and V are the key and value types of a Map[K, V].

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[T]

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 length size where each element is initialized to value.
  • size must be a non-negative Integer.
  • The element type is inferred from value, or checked against Array[T] when the target array type is declared explicitly.

Methods

Method Arguments Returns Description Complexity
get index: Integer T Read element at index. O(1) / O(1)
add value: T Void Append value. O(1) amortized / O(1)
add_at index: Integer, value: T 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: T Boolean Membership test. O(n) / O(1)
index_of elem: T 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[T] Return reversed array. O(n) / O(n)
set index: Integer, value: T Void Replace element at index. O(1) / O(1)
sort none Array[T] Return a new array sorted by built-in order or Comparable.compare. O(n log n) / O(n)
sort compareFn: Function(a: T, b: T): Integer Array[T] 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: Array[T] 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 or Comparable.
  • sort(compareFn) uses the provided comparator function instead. The comparator must return an Integer: negative when a < b, positive when a > b, 0 when equal.

Map[K, V]

Construction

{}

Methods

Method Arguments Returns Description Complexity
get key: K V Read value for key (fails if key missing). O(1) avg / O(1)
try_get key: K, default: V V Read value or default if missing. O(1) avg / O(1)
set key: K, value: V Void Add/replace key-value entry. O(1) avg / O(1)
put key: K, value: V 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: K Boolean Key existence test. O(1) avg / O(1)
keys none Array[K] Array of keys. O(n) / O(n)
values none Array[V] Array of values. O(n) / O(n)
remove key: K 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: Map[K, V] 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.

Map_Entry[K, V]

A Map_Entry[K, V] is the read-only key/value pair produced when a Map is iterated with across or a MapCursor. It cannot be created directly and has no mutators.

across {"name": "Ada"} as entry do
  print(entry.key + ": " + entry.value)
end
Method Arguments Returns Description
key none K The entry's key.
value none V The entry's value.
get index: Integer Any Pair-style access: 0 is the key, 1 is the value. Kept for older code; prefer key and value.
to_string none String Render as key: value, e.g. "name": "Ada".
equals other: Any Boolean True when both key and value are deeply equal.

Set[T]

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: Set[T] 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.empty creates an empty heap that uses natural ordering.
  • empty() is intended for element types that already support ordering: built-in sortable scalars or classes implementing Comparable.
  • For non-Comparable element types, use from_comparator(...).
  • from_comparator(compare) expects a Function(a: T, b: T): Integer comparator: negative when the first value is smaller, positive when larger, 0 when 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

  • pop and peek usually 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