silk/vector
Profiles: aarch64-apple-darwin, aarch64-unknown-linux-gnu, aarch64-unknown-linux-gnu-no-libc, wasm32-unknown-unknown, x86_64-unknown-linux-gnu, x86_64-unknown-linux-gnu-no-libc.
Growable owned sequences with allocation-aware mutation, stable sorting, and checked indexing.
When to use
Use Vector when a sequence must grow or own a runtime-determined number of values. Use a
fixed array when the length is part of the type, and silk.bytes.Bytes for bulk byte storage.
Details
make is allocation-free. The first growth reserves four elements and later growth doubles
capacity; reserve can move that cost ahead of mutation. Growth completes in replacement
storage before committing, so append and reserve leave the vector unchanged on
OutOfMemoryError. Removing, clearing, and truncating drop exactly the elements they discard
while retaining capacity.
sort is stable, deterministic, and supports move-only elements, but allocates scratch space.
binarySearch requires an already sorted vector and returns the lowest index among equal
matches.
Gotchas
get, set, and remove trap on an out-of-range index. An insert position must be at
or before the current length. Use asSlice to borrow move-only elements because get
produces a copied value.
Examples
Grow and edit an owned sequence
import silk.allocator { Allocator, OutOfMemoryError }
import silk.effect { Effect }
import silk.vector { Vector }
effect fn build() -> i32
! OutOfMemoryError {
let mut allocator = Allocator.systemAllocatorProvider()
let mut values = Vector.make<i32>()
let first = run Vector.append<i32>(&mut values, 10)
|> Effect.provideMut<Allocator>(&mut allocator)
let second = run Vector.append<i32>(&mut values, 30)
|> Effect.provideMut<Allocator>(&mut allocator)
let middle = run Vector.insert<i32>(&mut values, 1, 20)
|> Effect.provideMut<Allocator>(&mut allocator)
let changed = Vector.set<i32>(&mut values, 2, 22)
let removed = Vector.remove<i32>(&mut values, 0)
return Vector.get<i32>(&values, 0) + Vector.get<i32>(&values, 1)
}
effect fn recover(error: OutOfMemoryError) -> i32 {
return 0
}
pub fn main() -> i32 {
return run Effect.catchAll(build(), recover)
}Sort values and find the first equal value
import silk.allocator { Allocator, OutOfMemoryError }
import silk.effect { Effect }
import silk.option { Option }
import silk.usize
import silk.vector { Vector }
effect fn search() -> i32
! OutOfMemoryError {
let mut allocator = Allocator.systemAllocatorProvider()
let mut values = Vector.make<i32>()
let first = run Vector.append<i32>(&mut values, 3)
|> Effect.provideMut<Allocator>(&mut allocator)
let second = run Vector.append<i32>(&mut values, 36)
|> Effect.provideMut<Allocator>(&mut allocator)
let third = run Vector.append<i32>(&mut values, 3)
|> Effect.provideMut<Allocator>(&mut allocator)
let sorting = Vector.sort<i32>(&mut values)
|> Effect.provideMut<Allocator>(&mut allocator)
let sorted = run sorting
let found = Vector.binarySearch<i32>(&values, 3)
|> Option.unwrapOr<usize>(99)
if found != usize.ZERO {
return 0
}
return Vector.get<i32>(&values, 0) + Vector.get<i32>(&values, 1) + Vector.get<i32>(&values, 2)
}
effect fn recover(error: OutOfMemoryError) -> i32 {
return 0
}
pub fn main() -> i32 {
return run Effect.catchAll(search(), recover)
}Import as Vector with import silk.vector { Vector }.
Public declarations: 3.
Empty
pub struct Empty<T>The allocation-free storage state of an empty Vector.
Full
pub struct Full<T>The allocated storage state of a non-empty or reserved Vector.
Vector
pub struct Vector<T>Owns an initialized prefix of a growable contiguous allocation.
Details
The vector releases each initialized element and its storage on drop. Length counts initialized elements. Capacity counts elements that fit without growth. Borrowed elements retain their referent lifetimes through replacement, extraction, and required cleanup. An allocation does not make its payload detached.
Associated function Vector.make
pub fn make<T>() -> silk/vector.Vector<T>Creates an empty vector with zero capacity and no allocation.
Method Vector.length
pub fn length<T, 'life1>(self: &'life1 Vector<T>) -> usizeReturns the number of initialized elements.
Method Vector.capacity
pub fn capacity<T, 'life1>(self: &'life1 Vector<T>) -> usizeReturns the total number of elements that fit without another growth allocation.
Method Vector.asSlice
pub fn asSlice<T, 'life1>(self: &'life1 Vector<T>) -> &'life1 [T]Borrows the initialized elements as one shared lexical slice.
Gotchas
Do not retain this slice across an operation that can grow the vector.
Method Vector.asMutSlice
pub fn asMutSlice<T, 'life1>(self: &'life1 mut Vector<T>) -> &'life1 mut [T]Borrows all initialized elements as one exclusive lexical slice.
Gotchas
Do not retain this slice across an operation that can grow the vector.
Method Vector.append
pub effect<'env> fn append<T: 'env, 'life1: 'env, 'env>(self: &'life1 mut Vector<T>, value: T) -> () ! OutOfMemoryError ? &mut AllocatorAppends one owned value, growing geometrically when capacity is exhausted.
Details
The vector takes ownership of value. If growth fails, the vector keeps its prior contents,
length, and capacity.
Method Vector.insert
pub effect<'env> fn insert<T: 'env, 'life1: 'env, 'env>(self: &'life1 mut Vector<T>, index: usize, value: T) -> () ! OutOfMemoryError ? &mut AllocatorInserts one owned value at an index, shifting later elements without requiring T to be Copy.
Details
Existing elements from index onward move one position to the right. If growth fails, the
vector keeps its prior contents, length, and capacity.
Gotchas
index must be less than or equal to length.
Method Vector.get
pub fn get<T, 'life1>(self: &'life1 Vector<T>, index: usize) -> TCopies the element at one index and traps when the index is out of range.
When to use
Use this function for a Copy element. Use asSlice to borrow a move-only element.
Method Vector.pop
pub fn pop<T, 'life1>(self: &'life1 mut Vector<T>) -> silk/option.Option<T>Removes the last element and returns it. Returns an absent value for an empty vector.
Details
A present result transfers ownership of the removed element. Capacity does not change.
Method Vector.remove
pub fn remove<T, 'life1>(self: &'life1 mut Vector<T>, index: usize) -> TRemoves the element at one index, shifting the later elements down. Traps out of range.
Details
Ownership of the removed element passes to the caller. Capacity does not change.
Method Vector.clear
pub fn clear<T, 'life1>(self: &'life1 mut Vector<T>) -> ()Drops every initialized element and sets the length to zero, keeping the capacity.
Method Vector.truncate
pub fn truncate<T, 'life1>(self: &'life1 mut Vector<T>, length: usize) -> ()Drops every element past one length, keeping the capacity. Shorter lengths are left alone.
Details
If length is not less than the current length, this function does nothing.
Method Vector.set
pub fn set<T, 'life1>(self: &'life1 mut Vector<T>, index: usize, value: T) -> ()Overwrites the element at one index, dropping the old element first. Traps out of range.
Method Vector.reserve
pub effect<'env> fn reserve<T: 'env, 'life1: 'env, 'env>(self: &'life1 mut Vector<T>, additional: usize) -> () ! OutOfMemoryError ? &mut AllocatorGrows capacity to hold at least additional more elements without another allocation.
Details
This function does not change the length. If allocation fails, contents, length, and capacity remain unchanged.
Method Vector.reserveExact
pub effect<'env> fn reserveExact<T: 'env, 'life1: 'env, 'env>(self: &'life1 mut Vector<T>, additional: usize) -> () ! OutOfMemoryError ? &mut AllocatorReserves space for additional elements without geometric capacity growth.
When to use
Use when the complete output length is known. Use reserve for repeated growth.
Details
If the current capacity is sufficient, this function does not allocate or shrink storage.
Otherwise, one allocation sets capacity to the current length plus additional.
The length stays unchanged. Size overflow or allocation failure leaves all existing state unchanged.
Method Vector.sort
pub effect<'env> fn sort<T: 'env, 'life1: 'env, 'env>(self: &'life1 mut Vector<T>) -> () ! OutOfMemoryError ? &mut AllocatorOrders the elements in place. Equal elements keep their input order.
Details
The sort is stable and deterministic. It supports move-only elements and allocates scratch storage. If allocation fails, the vector remains unchanged.
Method Vector.binarySearch
pub fn binarySearch<T, 'life1>(self: &'life1 Vector<T>, target: T) -> silk/option.Option<usize>Returns the index of a matching element in a sorted vector, or an absent value when Option.none matches.
Details
Returns the lowest matching index when a vector holds several equal elements, so a repeated
search over one vector always answers with the same index.
This function consumes target and does not change the vector.
Gotchas
The vector must already be ordered by the same Order witness.
Method Vector.appendBytes
pub effect<'env> fn appendBytes<'life1: 'env, 'life2: 'env, 'env>(self: &'life1 mut silk/vector.Vector<u8>, values: &'life2 [u8]) -> () ! OutOfMemoryError ? &mut AllocatorAppends every byte of one borrowed sequence in source order with one bulk copy.
Details
If growth fails, the vector keeps its prior contents, length, and capacity.
Implementation Drop for silk/vector.Vector<T>
impl Drop for silk/vector.Vector<T>