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.
let empty: Set = Set()
let values = Set(1, "1", 1.0, true, null, 1)
print(values.len())
print(values)Output:
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.
| Method | Result | Contract |
|---|---|---|
add(value: Any) | Unit | Insert a validated scalar value if absent. |
clear() | Unit | Remove all members and release bucket storage. |
contains(value: Any) | Bool | Return whether a validated scalar value is present. |
copy() | Set | Return an independent Set in the same insertion order. |
difference(other: Set) | Set | Return left members absent from the right operand. |
intersection(other: Set) | Set | Return left members also present in the right operand. |
is_empty() | Bool | Return whether there are no members. |
len() | Int64 | Return the live unique member count. |
remove(value: Any) | Unit | Remove a validated scalar value if present. |
symmetric_difference(other: Set) | Set | Return members present in exactly one operand. |
to_list() | List | Return an insertion order snapshot of the members. |
union(other: Set) | Set | Return 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:
| Operation | Result order |
|---|---|
difference | Left only members in left order. |
intersection | Shared members in left order. |
symmetric_difference | Left only members in left order, followed by right only members in right order. |
union | Every 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 method | Time | Additional space |
|---|---|---|
Set(...values: Any) | Expected O(n) for n inputs; worst O(n²) under collisions | O(u) new Set. |
add(value: Any) | Expected amortized O(1); worst O(n), including rehash | O(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 collisions | O(n) new Set. |
difference(other: Set) | Expected O(n); worst O(nm + r² + n) under collisions | O(r) new Set, where r <= n. |
intersection(other: Set) | Expected O(n); worst O(nm + r² + n) under collisions | O(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 collisions | O(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 collisions | O(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
| Condition | Diagnostic |
|---|---|
| Unsupported member or NaN passed to a member operation | 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 specialization; Unit member | 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 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
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:
3
true
Set("write", "check", "read")Set algebra
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:
Set(3, 1, 2, 4, 5)
Set(1, 2)
Set(3)
Set(3, 4, 5)Independent copies
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:
true
false
2
3In 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.