Browse documentation
Data structures

Set

Unique scalar membership, insertion order, set operations, and time and space complexity.

Set is a built in, mutable collection of unique scalar values. It preserves insertion order. The native implementation uses a hash index with insertion order links.

Declaration and construction

Set requires no import and no type argument. Its constructor accepts zero or more positional scalar values, evaluated once in source order. Named constructor arguments are not supported. Duplicate inputs are stored once.

aner
let empty: Set = Set()
let values = Set(1, "1", 1.0, true, null, 1)
print(values.len())
print(values)

Output:

text
5
Set(1, "1", 1.0, true, null)

Set may be used in parameters, fields, return types, checked casts, and concrete arguments to user defined generic classes. Typed specializations are not supported. Set is a reserved built in name.

A binding inferred as Set 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 Set.

Member contract

Members may be Bool, Int64, non NaN Float64, String, or null. Their concrete runtime type is part of identity. Integer 1, float 1.0, Boolean true, and String "1" are four distinct members.

Float64 -0.0 and 0.0 compare equal and have the same hash. Positive and negative infinity produced by arithmetic are valid members. NaN is not valid because it does not have reflexive numeric equality. Unit, collections, user objects, and native composite values are not valid members.

Validation applies to membership tests and removal as well as insertion, including on an empty Set. There is no automatic numeric conversion, deep equality, custom hash callback, or custom equality callback.

Insertion order

Adding an existing member does not change its position. Removing an absent member is an operation with no effect. Removing and re adding a member moves it to the end. to_list() returns a separate insertion order snapshot. The List reference specifies operations on that result container.

Aliases and copies

Assignment shares the Set reference. Set equality is reference identity: an alias equals the original, while a separate Set or copy() has a different identity. copy() creates an independent Set with the same member order and copies owned String payloads. Set members contain no nested graphs.

Methods

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.

MethodResultContract
add(value: Any)UnitInsert a validated scalar value if absent.
clear()UnitRemove all members and release bucket storage.
contains(value: Any)BoolReturn whether a validated scalar value is present.
copy()SetReturn an independent Set in the same insertion order.
difference(other: Set)SetReturn left members absent from the right operand.
intersection(other: Set)SetReturn left members also present in the right operand.
is_empty()BoolReturn whether there are no members.
len()Int64Return the live unique member count.
remove(value: Any)UnitRemove a validated scalar value if present.
symmetric_difference(other: Set)SetReturn members present in exactly one operand.
to_list()ListReturn an insertion order snapshot of the members.
union(other: Set)SetReturn all members present in either operand.

Set algebra

Algebra operations allocate a new Set and leave both inputs unchanged. Their result order is defined as follows:

OperationResult order
differenceLeft only members in left order.
intersectionShared members in left order.
symmetric_differenceLeft only members in left order, followed by right only members in right order.
unionEvery left member in left order, followed by right only members in right order.

Algebra accepts a Set operand. It does not automatically convert other container types.

Time and space complexity

Let n be the receiver's live member count, m the other Set's member count, r the result's member count, b the allocated hash bucket count, and u the unique constructor input count. Constructor bounds use n for the total number of supplied inputs. Bounds assume fixed length scalar values. Space below is additional auxiliary, result, or new persistent storage beyond existing Sets and evaluated arguments.

Expected hash bounds require well distributed hashes. Hash lookup does not guarantee constant time; a collision chain can take O(n).

Constructor or methodTimeAdditional space
Set(...values: Any)Expected O(n) for n inputs; worst O(n²) under collisionsO(u) new Set.
add(value: Any)Expected amortized O(1); worst O(n), including rehashO(1) new entry; worst O(n) transient bucket growth.
clear()O(n + b)O(1) auxiliary; members and buckets are released.
contains(value: Any)Expected O(1); worst O(n)O(1).
copy()Expected O(n); worst O(n²) under collisionsO(n) new Set.
difference(other: Set)Expected O(n); worst O(nm + r² + n) under collisionsO(r) new Set, where r <= n.
intersection(other: Set)Expected O(n); worst O(nm + r² + n) under collisionsO(r) new Set, where r <= min(n, m).
is_empty()O(1)O(1).
len()O(1)O(1).
remove(value: Any)Expected O(1); worst O(n)O(1); the entry is released and bucket capacity is retained.
symmetric_difference(other: Set)Expected O(n + m); worst O((n + m)²) under collisionsO(r) new Set, where r <= n + m.
to_list()O(n)O(n) new List and copied scalar values.
union(other: Set)Expected O(n + m); worst O((n + m)²) under collisionsO(r) new Set, where r <= n + m.

Total Set container storage is O(n + b), plus owned member bytes. Every member occupies one stored value slot. Hash entries and insertion order links share the stored member. Deletion releases entries immediately, while buckets may retain earlier capacity. Deleted entries do not accumulate as tombstones. clear releases buckets.

Algebra uses hash membership and insertion. Its collision bounds include both membership checks and result construction. During result construction, the native implementation also materializes selected values in an O(r) temporary sequence; the asymptotic additional space remains O(r).

Hashing a String of k bytes costs O(k). String comparisons may inspect shared prefixes; collisions multiply that cost by the number of comparisons. Copying or storing an owned String of p bytes can add O(p) time and storage. Add these payload costs to constructor, copy, snapshot, and algebra bounds.

These 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 total heap size. With h outstanding heap objects, s traced 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

ConditionDiagnostic
Unsupported member or NaN passed to a member operationR2901
Collection resource limit failureR2901
Host memory allocation failure in command line executionE9003
Wrong static argument type or arity; named constructor arguments; typed specialization; Unit memberE1002
Failed checked cast or unsupported Any equality operatorR1002

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 Sets 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 Set member occupies one slot. Every owned String copy contributes its stored byte count; suppressing a duplicate does not add storage for that member.

Copy, snapshot, and algebra results must fit the same limits. The limits are not a whole process RAM quota: native buffers, heap metadata, retained source, allocator overhead, and ordinary user class String fields are excluded.

Unreachable values 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 remove release direct member and String accounting.

Display is a bounded preview: at most 50 members and 8,192 output bytes. The collection renderer also bounds nested collection display to eight levels; Set members themselves are scalar. Strings are quoted and escaped, and omitted members use .... Display is not serialization; output storage is O(output bytes).

Examples

Membership and mutation

aner
let values = Set("read", "write")
values.add("read")
values.add("check")
print(values.len())
print(values.contains("read"))
values.remove("read")
values.remove("missing")
values.add("read")
print(values)

Output:

text
3
true
Set("write", "check", "read")

Set algebra

aner
let left = Set(3, 1, 2)
let right = Set(2, 4, 1, 5)
print(left.union(right))
print(left.intersection(right))
print(left.difference(right))
print(left.symmetric_difference(right))

Output:

text
Set(3, 1, 2, 4, 5)
Set(1, 2)
Set(3)
Set(3, 4, 5)

Independent copies

aner
let original = Set(1, 2)
let alias = original
let copied = original.copy()
copied.add(3)
print(original == alias)
print(original == copied)
print(original.len())
print(copied.len())

Output:

text
true
false
2
3

In VS Code, the set snippet provides an Aner example. Signature help describes parameters, result types, complexity, and scalar member constraints. The editor and native executable must support the same API.

Aner documentation · Reference and guides