Silk

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>) -> usize

Returns the number of initialized elements.

Method Vector.capacity

pub fn capacity<T, 'life1>(self: &'life1 Vector<T>) -> usize

Returns 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 Allocator

Appends 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 Allocator

Inserts 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) -> T

Copies 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) -> T

Removes 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 Allocator

Grows 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 Allocator

Reserves 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 Allocator

Orders 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 Allocator

Appends 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>

On this page