Module imm/sorted_map

imm/sorted_map
Stability: unstable — the same open shape as `imm.Map` (`plans/STD_API_STABILIZATION.md` §4): `remove(key) -> Self` cannot report whether the key was there, and deciding that changes this signature. The eager `imm.List` iteration above is the other known gap, and a stack-based in-order cursor is the intended fix; that one is additive. — stable modules only change additively; this one may still change.

Persistent immutable sorted map using a left-leaning red-black tree.

SortedMap(K, V) stores key-value pairs in sorted order by key. All mutations return new maps, leaving the original unchanged. Backed by atomic object nodes for thread-safe structural sharing.

Keys must implement Eq, Ord, and Send. Values must implement Send.

Examples

{ SortedMap } :: import "std/imm/sorted_map";

m := SortedMap(i32, i32).new();
m = m.insert(i32(3), i32(30));
m = m.insert(i32(1), i32(10));
m = m.insert(i32(2), i32(20));
// keys are always sorted: 1, 2, 3

A left-leaning red-black tree keeps the depth in O(log n), so get, insert and remove are all O(log n) and a mutation copies only the nodes on its path — the rest is shared with the map it came from. This is the ordered counterpart of imm.Map's HAMT: reach for it when iteration must come out in key order. keys/values/entries, and the IntoIterator behind for(map, ...), MATERIALIZE an imm.List in key order first — O(n) time and allocation, not a lazy in-order cursor.

Stability

unstable — the same open shape as imm.Map (plans/STD_API_STABILIZATION.md §4): remove(key) -> Self cannot report whether the key was there, and deciding that changes this signature. The eager imm.List iteration above is the other known gap, and a stack-based in-order cursor is the intended fix; that one is additive.

Types

SortedMap type-function
fn(K : Type, V : Type) -> Type

Persistent immutable sorted map backed by a left-leaning red-black tree.

Type Parameters

NameTypeNotes
KTypecomptime
VTypecomptime

Trait Implementations

impl(generic(K : Type, V : Type), where(K <: (Eq(K), Ord(K), Send, Acyclic), V <: (Send, Acyclic)), SortedMap(K, V), Acyclic())
impl(generic(K : Type, V : Type), where(K <: (Eq(K), Ord(K), Send, Acyclic), V <: (Send, Acyclic)), SortedMap(K, V), ...)
new : (fn() -> Self)

Create an empty sorted map.

Returns: Self

len : (fn(self : Self) -> usize)

Number of entries.

Returns: usize

is_empty : (fn(self : Self) -> bool)

Check if the map is empty.

Returns: bool

get : (fn(self : Self, key : K) -> Option(V))

Look up a value by key.

Returns: Option(V)

contains_key : (fn(self : Self, key : K) -> bool)

Check if a key exists.

Returns: bool

insert : (fn(self : Self, key : K, value : V) -> Self)

Return a new map with the key-value pair inserted (or updated).

Returns: Self

remove : (fn(self : Self, key : K) -> Self)

Return a new map with the key removed — im's without. A key that is not present gives back self itself, not a copy.

This deliberately does NOT report what it removed; extract is the form that does.

Returns: Self

extract : (fn(self : Self, key : K) -> Option(Tuple(V, Self)))

The value at key together with the map WITHOUT it, or .None when the key is absent — im's extract, and the form remove is not: remove answers only "the map afterwards".

Two walks of the tree, as remove itself already does (it asks _node_contains before rebuilding), so this costs one lookup more than remove and nothing more than get + remove written by hand.

Returns: Option(Tuple(V, Self))

min_key : (fn(self : Self) -> Option(K))

Get the minimum key in the map.

Returns: Option(K)

max_key : (fn(self : Self) -> Option(K))

Get the maximum key by going right.

Returns: Option(K)

keys : (fn(self : Self) -> List(K))

Return in-order list of keys.

Returns: List(K)

values : (fn(self : Self) -> List(V))

Return list of values in key order.

Returns: List(V)

entries : (fn(self : Self) -> List(MapEntry(K, V)))

Return in-order list of entries — the counterpart of imm.Map.entries, and what into_iter walks.

Returns: List(MapEntry(K, V))

from_entries : (fn(pairs : ArrayList(MapEntry(K, V))) -> Self)

Create a sorted map from a slice of key-value pairs.

Returns: Self

impl(generic(K : Type, V : Type), where(K <: (Eq(K), Ord(K), Send, Acyclic), V <: (Eq(V), Send, Acyclic)), SortedMap(K, V), Eq(SortedMap(K, V))(...))
impl(generic(K : Type, V : Type), where(K <: (Eq(K), Ord(K), Send, Acyclic), V <: (Send, Acyclic)), SortedMap(K, V), IntoIterator(...))
Item : MapEntry(K, V)
IntoIter : ListIter(MapEntry(K, V))
into_iter : (fn(self : Self) -> ListIter(MapEntry(K, V)))

Returns: ListIter(MapEntry(K, V))

impl(generic(K : Type, V : Type), where(K <: (Eq(K), Ord(K), Send, Acyclic), V <: (Send, Acyclic)), SortedMap(K, V), Default(...))
default : (fn() -> Self)

The default value of the type.

Returns: Self

RBNode type-function
fn(K : Type, V : Type) -> Type

Internal LLRB tree node — an atomic object for thread-safe sharing.

Type Parameters

NameTypeNotes
KTypecomptime
VTypecomptime

Trait Implementations

impl(generic(K : Type, V : Type), where(K <: (Eq(K), Ord(K), Send, Acyclic), V <: (Send, Acyclic)), RBNode(K, V), Acyclic())
Color enum
Color

Color of a red-black tree node.

Variants

VariantFieldsDescription
Red
Black