Skip to content

Collections · API

SlotMap

Stores values under handles. A handle to a removed value reads nil, even once its slot is reused, because removing a value bumps its slot’s generation. A slot is reused 65,535 times, then retired.

Values sit packed in one list, so SlotMap:Iter and SlotMap:RawValues see no gaps. Removing a value moves the last one into its place, so the order changes.

local Enemies = Collections.SlotMap.new()
local Goblin = Enemies:Insert("goblin")
Enemies:Remove(Goblin)
local Orc = Enemies:Insert("orc")
print(Enemies:Get(Goblin), Enemies:Get(Orc)) -- nil orc
Member Description
.PackHandle() Builds a handle from a slot and a generation, as Collections.PackHandle does.
.UnpackHandle() Splits a handle into its slot and generation, as Collections.UnpackHandle does.
.new() Creates an empty map.
:Insert() Stores Value in the lowest free slot and returns its handle.
:Get() Returns the value under Handle, or nil if it was removed.
:Set() Replaces the value under Handle, and returns false if Handle was removed.
:Remove() Removes the value under Handle and returns it, or nil if it was already removed.
:IsAlive() Whether Handle still has a value.
:Count() How many values it holds.
:Capacity() How many slots fit before it next grows.
:Iter() Returns an iterator over every handle and value, from the last packed value back to the first.
:RawValues() Returns the packed values and their count: the table that holds them, or with a NumericBackend, a buffer of Stride bytes per value from byte 0.
:Clear() Removes every value at once.
NumericBackend How a SlotMap stores its values in a buffer, as its Config’s Backend.
Config Settings for SlotMap.new.
SlotMap The type SlotMap.new returns.
function SlotMap.PackHandle(Slot: number, Generation: number): number

Builds a handle from a slot and a generation, as Collections.PackHandle does.

function SlotMap.UnpackHandle(Handle: number): (number, number)

Splits a handle into its slot and generation, as Collections.UnpackHandle does.

function SlotMap.new(Config: Config?): SlotMap

Creates an empty map.

function SlotMap:Insert(Value: any): number

Stores Value in the lowest free slot and returns its handle. With a NumericBackend, a Value it cannot write raises and stores nothing.

function SlotMap:Get(Handle: any): any

Returns the value under Handle, or nil if it was removed.

function SlotMap:Set(Handle: any, Value: any): boolean

Replaces the value under Handle, and returns false if Handle was removed.

function SlotMap:Remove(Handle: any): any

Removes the value under Handle and returns it, or nil if it was already removed.

function SlotMap:IsAlive(Handle: any): boolean

Whether Handle still has a value.

function SlotMap:Count(): number

How many values it holds.

function SlotMap:Capacity(): number

How many slots fit before it next grows.

function SlotMap:Iter(): () -> (number?, any)

Returns an iterator over every handle and value, from the last packed value back to the first. The loop may remove the entry it is on; an entry it inserts is not visited.

function SlotMap:RawValues(): (any, number)

Returns the packed values and their count: the table that holds them, or with a NumericBackend, a buffer of Stride bytes per value from byte 0. An Insert can replace the buffer, so take it again after one.

Returns Description
any the values
number how many
function SlotMap:Clear()

Removes every value at once. Every handle given out so far stops matching.

export type NumericBackend = {
	Stride: number,
	Read: (b: buffer, offset: number) -> any,
	Write: (b: buffer, offset: number, v: any) -> (),
}

How a SlotMap stores its values in a buffer, as its Config’s Backend. A Stride of 4 whose Read and Write round-trip full 32-bit words as buffer.readu32 and buffer.writeu32 do is swapped for those two at new.

Field Type Description
Stride number bytes per value
Read (b: buffer, offset: number) -> any reads one value
Write (b: buffer, offset: number, v: any) -> () writes one value
export type Config = {
	InitialCapacity: number?,
	Backend: ("Table" | NumericBackend)?,
}

Settings for SlotMap.new.

Field Type Description
InitialCapacity number? slots to make room for up front, 8 by default, rounded up to a power of two
Backend ("Table" | NumericBackend)? “Table” by default, which holds any value
export type SlotMap = {
	Insert: (self: SlotMap, Value: any) -> number,
	Get: (self: SlotMap, Handle: any) -> any,
	Set: (self: SlotMap, Handle: any, Value: any) -> boolean,
	Remove: (self: SlotMap, Handle: any) -> any,
	IsAlive: (self: SlotMap, Handle: any) -> boolean,
	Count: (self: SlotMap) -> number,
	Capacity: (self: SlotMap) -> number,
	Iter: (self: SlotMap) -> () -> (number?, any),
	RawValues: (self: SlotMap) -> (any, number),
	Clear: (self: SlotMap) -> (),
}

The type SlotMap.new returns.

© 2026 PRMS Developer