silk/vector
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 }
import silk.effect { Effect }
import silk.vector as Vector
effect fn build() -> i32
! Allocator.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: Allocator.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 }
import silk.effect { Effect }
import silk.option as Option
import silk.usize as usize
import silk.vector as Vector
effect fn search() -> i32
! Allocator.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: Allocator.OutOfMemoryError) -> i32 {
return 0
}
pub fn main() -> i32 {
return run Effect.catchAll(search(), recover)
}Import as Vector with import silk.vector.
Public declarations: 20.
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.
make
pub fn make<T>() -> silk/vector.Vector<T>Creates an empty vector with zero capacity and no allocation.
length
pub fn length<T>(self: &silk/vector.Vector<T>) -> usizeReturns the number of initialized elements.
capacity
pub fn capacity<T>(self: &silk/vector.Vector<T>) -> usizeReturns the total number of elements that fit without another growth allocation.
asSlice
pub fn asSlice<T>(self: &silk/vector.Vector<T>) -> &[T]Borrows the initialized elements as one shared lexical slice.
Gotchas
Do not retain this slice across an operation that can grow the vector.
asMutSlice
pub fn asMutSlice<T>(self: &mut silk/vector.Vector<T>) -> &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.
Implementation Drop for silk/vector.Vector<T>
impl Drop for silk/vector.Vector<T>append
pub effect fn append<T>(self: &mut silk/vector.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.
appendBytes
pub effect fn appendBytes(self: &mut silk/vector.Vector<u8>, values: &[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.
insert
pub effect fn insert<T>(self: &mut silk/vector.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.
Implementation Copy for silk/vector.Read<T>
impl Copy for silk/vector.Read<T>get
pub fn get<T>(self: &silk/vector.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.
pop
pub fn pop<T>(self: &mut silk/vector.Vector<T>) -> 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.
remove
pub fn remove<T>(self: &mut silk/vector.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.
clear
pub fn clear<T>(self: &mut silk/vector.Vector<T>) -> ()Drops every initialized element and sets the length to zero, keeping the capacity.
truncate
pub fn truncate<T>(self: &mut silk/vector.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.
set
pub fn set<T>(self: &mut silk/vector.Vector<T>, index: usize, value: T) -> ()Overwrites the element at one index, dropping the old element first. Traps out of range.
reserve
pub effect fn reserve<T>(self: &mut silk/vector.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.
sort
pub effect fn sort<T>(self: &mut silk/vector.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.
binarySearch
pub fn binarySearch<T>(self: &silk/vector.Vector<T>, target: T) -> Option<usize>Returns the index of a matching element in a sorted vector, or an absent value when 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.