Set Tables
import { Aside } from '@astrojs/starlight/components';
Set tables store key-value pairs where each key maps to exactly one value. Inserting with an existing key overwrites the previous value. This is the most common table type, ideal for caches, configuration, and general-purpose persistence.
Set tables are provided by the slate/set module and correspond to the set table type in Erlang's DETS.
Opening and closing
Section titled “Opening and closing”import slate/set
let assert Ok(table) = set.open("data/users.dets")
// ... use the table ...
let assert Ok(Nil) = set.close(table)For safer lifecycle management, use with_table instead.
Inserting data
Section titled “Inserting data”// Insert a single key-value pair (overwrites if key exists)let assert Ok(Nil) = set.insert(table, "alice", 42)
// Batch insert multiple pairslet assert Ok(Nil) = set.insert_list(table, [ #("alice", 42), #("bob", 37), #("charlie", 25),])Insert without overwriting
Section titled “Insert without overwriting”Use insert_new to insert only if the key does not already exist. Returns Error(KeyAlreadyPresent) if the key is taken.
let assert Ok(Nil) = set.insert_new(table, "alice", 42)let assert Error(slate.KeyAlreadyPresent) = set.insert_new(table, "alice", 99)Looking up data
Section titled “Looking up data”// Get the value for a key (returns Error(NotFound) if missing)let assert Ok(42) = set.lookup(table, key: "alice")let assert Error(slate.NotFound) = set.lookup(table, key: "unknown")
// Check if a key exists without retrieving the valuelet assert Ok(True) = set.member(table, key: "alice")let assert Ok(False) = set.member(table, key: "unknown")Deleting data
Section titled “Deleting data”// Delete a single keylet assert Ok(Nil) = set.delete_key(table, key: "alice")
// Delete a specific key-value pair (equivalent to delete_key for sets)let assert Ok(Nil) = set.delete_object(table, key: "bob", value: 37)
// Clear all entrieslet assert Ok(Nil) = set.delete_all(table)Iterating over entries
Section titled “Iterating over entries”// Get all entries as a list (loads entire table into memory)let assert Ok(entries) = set.to_list(table)
// Fold over entries to compute a resultlet assert Ok(total) = set.fold(table, from: 0, with: fn(acc, _key, value) { acc + value})
// Get the number of stored entrieslet assert Ok(count) = set.size(table)Atomic counters
Section titled “Atomic counters”Set tables support atomic counter increments for integer values:
let assert Ok(Nil) = set.insert(table, "page_views", 0)let assert Ok(1) = set.update_counter(table, "page_views", 1)let assert Ok(3) = set.update_counter(table, "page_views", 2)let assert Ok(1) = set.update_counter(table, "page_views", -2)Table info
Section titled “Table info”let assert Ok(info) = set.info(table)// info.file_size — size of the file on disk in bytes// info.object_count — number of entries// info.kind — slate.SetOpening with options
Section titled “Opening with options”Repair policy
Section titled “Repair policy”Control how slate handles improperly closed tables:
import slate.{AutoRepair, ForceRepair, NoRepair}
// Default: auto-repair if neededlet assert Ok(table) = set.open_with("data/users.dets", AutoRepair)
// Force repair even if file appears cleanlet assert Ok(table) = set.open_with("data/users.dets", ForceRepair)
// Return an error instead of repairinglet assert Ok(table) = set.open_with("data/users.dets", NoRepair)Access mode
Section titled “Access mode”Open a table as read-only to prevent accidental writes:
import slate.{AutoRepair, ReadOnly}
let assert Ok(table) = set.open_with_access("data/users.dets", AutoRepair, ReadOnly)let assert Ok(42) = set.lookup(table, key: "alice")// set.insert(table, "alice", 99) would return Error(AccessDenied)