List
Ordered heterogeneous storage, mutation, compatible sorting, and time and space complexity.
List is a built in, mutable sequence. It preserves element order and duplicate values, provides indexed access, and supports elements with different concrete runtime types. Its native storage is a growable array of values.
Declaration and construction
List requires no import and no type argument. The constructor accepts zero or more positional values. Constructor arguments are evaluated once in source order. Named constructor arguments are not supported.
let empty: List = List()
let values = List(10, "hello", 1.5, true, null)
values.append("last")
print(values)Output:
List(10, "hello", 1.5, true, null, "last")List may be used in parameters, fields, return types, checked casts, and concrete arguments to user defined generic classes. List<Int64> and other typed specializations are not supported. List is a reserved built in name.
A binding inferred as List retains that static type. Use an explicit Any binding when its value must later have a different concrete type. A let binding prevents rebinding and permits mutation of the referenced List.
Element contract
An element may be an Int64, Float64, String, Bool, null, user object, native value, or nested collection. Unit () is not a valid element.
get, get_or, pop, and remove_at return static type Any. type_of(value) identifies its concrete runtime type. cast<Type>(value) checks that type without converting it. For example, an Int64 value cannot be cast to Float64; Float64(cast<Int64>(value)) performs an explicit numeric conversion.
let values = List(10, "hello")
print(type_of(values.get(0)))
print(cast<Int64>(values.get(0)) + 5)Output:
Int64
15Indexing
Indices have type Int64 and are zero based. Negative indices do not address elements from the end.
get,set, andremove_atrequire0 <= index < len().insertrequires0 <= index <= len(); the final position appends.get_orreturns its fallback for an index outside the valid range, including a negative index.poprequires a nonempty List.
All method arguments are evaluated before the method executes. A get_or fallback expression is evaluated even when the requested element exists.
Equality and membership
contains uses strict runtime equality. Scalars compare by value only when their concrete types match. Null compares equal to null. User objects and nested collections compare by reference identity. Integer 1, float 1.0, Boolean true, and String "1" are distinct values for membership.
Membership does not recursively compare nested collections. If a comparison reaches two same type native composite values without an equality operation, such as two Tensors, contains reports R2901. Values with different concrete runtime types compare unequal. NaN follows numeric equality and does not compare equal to itself.
A List itself compares by reference identity. An alias equals the original List; a separate List or copy() has a different identity. Comparing differently typed values requires compatible static types, for example an Any operand.
Aliases and copies
Assignment shares the List reference. copy() creates an independent outer List, copying owned scalar payloads and retaining shared references to nested collections and user objects. Native payloads preserve their existing copy or alias behavior. Copying does not recursively clone a nested graph.
let child = List(1)
let original = List(child)
let copied = original.copy()
cast<List>(copied.get(0)).append("shared")
copied.append("copy only")
print(child.len())
print(original.len())
print(copied.len())Output:
2
1
2Methods
Methods accept positional arguments or named arguments with the labels below. Named arguments select parameter destinations without changing expression evaluation order. A Unit result cannot be chained.
| Method | Result | Contract |
|---|---|---|
append(value: Any) | Unit | Append one value. |
clear() | Unit | Remove all elements and release List capacity. |
contains(value: Any) | Bool | Test strict runtime equality against the elements. |
copy() | List | Return a new shallow outer List. |
extend(other: List) | Unit | Append the other List's current elements in order. |
get(index: Int64) | Any | Return the element at a valid index. |
get_or(index: Int64, default: Any) | Any | Return the element or the fallback for an invalid index. |
insert(index: Int64, value: Any) | Unit | Insert at the given position and shift subsequent elements. |
is_empty() | Bool | Return whether the List has no elements. |
len() | Int64 | Return the live element count. |
pop() | Any | Remove and return the final element. |
remove_at(index: Int64) | Any | Remove and return the indexed element, shifting subsequent elements. |
set(index: Int64, value: Any) | Unit | Replace the indexed element. |
sort() | Unit | Stably reorder supported elements into ascending order. |
extend snapshots the source elements before appending. Extending a List with itself repeats its original contents once.
Sorting
sort() mutates the existing List. Every alias observes the resulting order. Sorting is stable: elements that compare equal retain their relative order and concrete runtime types.
| Element group | Ascending order |
|---|---|
| Bool only | false before true. |
| Int64, Float64, or a mixture of both | Numeric order without converting stored values or rounding large Int64 values to Float64. |
| String only | Case sensitive lexicographic order of encoded bytes. |
Numeric ordering places negative infinity first and positive infinity last. Equal Int64/Float64 numeric values and positive/negative zero retain their original relative order. Numeric ordering does not change the strict equality contract used by membership.
String ordering does not apply locale rules, natural number ordering, or Unicode normalization. Bool values cannot be mixed with numeric values.
An empty List may be sorted. Unsupported elements are rejected even in a one element List. Null, NaN, nested collections, user objects, native composites, and incompatible mixtures such as an Int64 with a String have no default sort order. No custom comparator or descending order argument is currently supported.
Sorting validates every element before mutation. Validation or allocation failure leaves the List contents and order unchanged. A runtime failure in a persistent notebook still clears the native Session according to the normal Session error contract.
The implementation validates the elements, stably merge sorts an index permutation, and moves values into the resulting order. It does not deep copy owned String payloads or traverse nested graphs.
Time and space complexity
Let n be the receiver's live length, m the other List's length, and c the allocated capacity. Bounds assume bounded cost values. Space below is additional auxiliary, result, or new persistent storage beyond the existing List and evaluated arguments.
| Constructor or method | Time | Additional space |
|---|---|---|
List(...values: Any) | O(n) for n inputs | O(n) new List. |
append(value: Any) | Amortized O(1); worst O(n) on growth | O(1) new slot; worst O(n) transient growth buffer. |
clear() | O(n) | O(1) auxiliary; capacity and contents are released. |
contains(value: Any) | O(n) worst | O(1). |
copy() | O(n) | O(n) new shallow List. |
extend(other: List) | O(m) amortized; worst O(n + m) on growth | O(m) new slots and O(m) auxiliary snapshot; up to O(n + m) transient growth storage. |
get(index: Int64) | O(1) | O(1) result, plus copied payload bytes. |
get_or(index: Int64, default: Any) | O(1) | O(1) result, plus copied payload bytes. |
insert(index: Int64, value: Any) | O(n) worst; final position amortized O(1) | O(1) new slot; worst O(n) transient growth buffer. |
is_empty() | O(1) | O(1). |
len() | O(1) | O(1). |
pop() | O(1) | O(1) auxiliary; the removed owned payload transfers to the result. |
remove_at(index: Int64) | O(n) worst; final position O(1) | O(1) auxiliary; the removed owned payload transfers to the result. |
set(index: Int64, value: Any) | O(1) | O(1) replacement, plus stored payload bytes. |
sort() | O(n) validation and O(n log n) sorting for n >= 2; O(1) for n <= 1 | O(n) auxiliary; no new List or deep payload copy. |
The List retains O(c) slots plus owned payload bytes. Geometric capacity growth provides the amortized append bound. pop and remove_at retain capacity; clear releases it.
A String of p bytes can add O(p) time and storage when copied or stored. A String comparison can inspect the shared prefix; String sorting performs O(n log n) comparisons and has worst case time O(n log n · (1 + k)) for maximum String length k. The auxiliary sorting space remains O(n). Native value copies retain their own payload costs. Nested collection and object references are shallow handles.
These operation bounds exclude parsing, argument evaluation, heap reference validation, automatic tracing, and display. The heap identity registry has expected constant time hash lookup; its collision cost depends on the total heap size. With h outstanding heap objects, s traced value slots, and g roots, tracing takes expected O(h + s + g) time and O(h) auxiliary space; hash collisions can increase the time.
Error behavior and resource limits
| Condition | Diagnostic |
|---|---|
Invalid index for strict access, removal, or insertion; pop on an empty List | R2901 |
| Unsupported or incompatible sort contents; NaN in sorting | R2901 |
Unsupported same type native equality encountered by contains | R2901 |
| Collection resource limit failure | R2901 |
| Host memory allocation failure in command line execution | E9003 |
| Wrong static argument type or arity; named constructor arguments; typed List specialization; Unit payload | E1002 |
| Failed checked cast or unsupported Any equality operator | R1002 |
A native runtime failure clears the entire notebook Session. A parsing or type checking failure preserves previous Session state. Saved notebook outputs do not reconstruct live Lists after a restart.
The execution heap permits 16,384 outstanding heap objects, 262,144 outstanding value slots, and 16 MiB of directly stored collection String bytes. These limits are shared with other heap backed values. Each List element occupies one slot. Every owned String copy contributes its stored byte count; a nested reference occupies one slot and does not recursively duplicate its referenced storage.
The limits do not constitute a whole process RAM quota. They exclude native payload buffers, heap metadata, retained source, allocator overhead, and ordinary user class String fields. Native values retain their own operation limits.
Unreachable objects and cycles are reclaimed after a successful shared session cell. There is no collection during a cell, so repeated temporary allocations can reach the limits before completion. clear and removals release direct element and String accounting; unreachable nested objects are reclaimed by the next successful session collection.
Display is a bounded preview: at most 50 entries per collection, eight nested collection levels, and 8,192 output bytes. Strings are quoted and escaped. Cycles and omitted contents use markers such as <cycle:List>, <depth-limit:List>, and .... Display is not serialization; its state uses O(depth) active path storage and O(output bytes) result storage.
Examples
Indexed mutation
let tasks = List("read", "write")
tasks.insert(index: 1, value: "check")
tasks.set(index: 0, value: "open")
print(tasks.remove_at(1))
print(tasks.pop())
print(tasks.get_or(index: 99, default: "no task"))Output:
check
write
no taskNumeric sorting
let numbers = List(3, 1.5, 1, -2.0)
numbers.sort()
print(numbers)Output:
List(-2.0, 1, 1.5, 3)String sorting and traversal
let words = List("pear", "apple", "banana")
words.sort()
var index = 0
while index < words.len() {
print(cast<String>(words.get(index)))
index = index + 1
}Output:
apple
banana
pearTraversal currently uses while and explicit methods. List literals, bracket indexing, general for loops, and iterator APIs are not supported.
In VS Code, the list and listsort snippets provide Aner examples. Signature help describes parameters, result types, complexity, and ordering constraints. The editor and native executable must support the same API.