xb5_trees (xb5 v1.0.1)
View SourceAn ordered key-value store backed by a
B-tree of order 5, and a drop-in
alternative to gb_trees.
Keys are kept in ascending Erlang term order. Comparisons use == rather than
=:= — so key 1 and key 1.0 are considered the same key.
Conversion to a list of {Key, Value} pairs via to_list/1 always yields
entries in ascending key order.
Beyond gb_trees
In addition to the gb_trees API, xb5_trees provides:
from_list/1— construct a tree from a list of{Key, Value}pairs.insert_with/3,update_with/3,update_with/4— insert or update lazily.foldl/3,foldr/3— left and right folds.merge/2,merge_with/3— merge two trees.intersect/2,intersect_with/3— intersect two trees.is_equal/2— test key-value equality.
See also
xb5_sets— ordered set.xb5_bag— ordered multiset with order-statistic operations.
Examples
> T = xb5_trees:from_list([{b, 2}, {a, 1}]).
> xb5_trees:get(a, T).
1
> xb5_trees:largest(T).
{b, 2}
Summary
Types
Shorthand for iter(_, _).
An iterator over entries of type {Key, Value}. See iterator/1 and next/1.
Shorthand for tree(_, _).
An ordered key-value tree containing entries of type {Key, Value}.
A plain-map representation of a tree, suitable for cross-language serialization (for example, converting to or from an Elixir struct that uses the same underlying node structures).
Functions
Returns Tree unchanged.
Removes key Key from Tree1, returning a new tree Tree2.
Removes key Key from Tree1 if present, returning a new tree Tree2.
If Key is not present, Tree1 is returned unchanged.
Inserts Key with value Value into Tree1 if the key is not present,
otherwise updates Key to value Value in Tree1.
Folds Function over all entries of Tree in ascending key order,
calling Function(Key, Value, AccIn) for each entry. Returns the final
accumulator value.
Folds Function over all entries of Tree in descending key order,
calling Function(Key, Value, AccIn) for each entry. Returns the final
accumulator value.
Returns a tree of the key-value pairs in List. Duplicate keys are
resolved by keeping the last occurrence.
Returns a tree built from the ordered dictionary Orddict.
Retrieves the value stored with Key in Tree.
Inserts Key with value Value into Tree1, returning a new tree
Tree2.
Like insert/3, but takes a zero-arity fun that is only evaluated when
the key is not yet present. Returns a new tree Tree2 with the key
inserted.
Returns the intersection of Tree1 and Tree2, i.e., a tree containing only
the keys present in both trees. For keys present in both, the value from
Tree2 is kept.
Returns the intersection of Tree1 and Tree2, using Fun to compute the
value for each key present in both trees. Fun is called as
Fun(Key, Value1, Value2) where Value1 is from Tree1 and Value2 is
from Tree2.
Returns true if Key is present in Tree, otherwise false.
Returns true if Tree is empty, otherwise false.
Returns true if Tree1 and Tree2 contain the same keys and values, otherwise
false.
Returns an iterator that can be used for traversing the entries of Tree;
see next/1. Equivalent to iterator(Tree, ordered).
Returns an iterator that can be used for traversing the entries of Tree
in the given Order; see next/1.
Returns an iterator that can be used for traversing the entries of Tree
starting from the first key greater than or equal to Key; see next/1.
Equivalent to iterator_from(Key, Tree, ordered).
Returns an iterator that can be used for traversing the entries of Tree
starting from the key nearest to Key in the given Order; see next/1.
Returns the keys in Tree as an ordered list.
Returns {Key2, Value} where Key2 is the least key strictly greater
than Key1 in Tree, or none if no such key exists.
Returns {Key, Value} where Key is the largest key in Tree.
Looks up Key in Tree. Returns {value, Value} if Key is present,
or none if Key is not present.
Maps Function over all values in Tree1, returning a new tree Tree2
with the same keys. For each entry, Function(Key, Value1) must return
the new value Value2.
Merges Tree1 and Tree2 into a single tree. For keys present in both trees,
the value from Tree2 is kept.
Merges Tree1 and Tree2 into a single tree, using Fun to compute the
value for each key present in both trees. Fun is called as
Fun(Key, Value1, Value2) where Value1 is from Tree1 and Value2 is
from Tree2.
Returns a new empty tree.
Returns {Key, Value, Iter2} where Key and Value are the next entry
referred to by iterator Iter1 and Iter2 is the updated iterator, or
none if no more entries remain.
Returns the number of entries in Tree.
Returns {Key2, Value} where Key2 is the greatest key strictly less
than Key1 in Tree, or none if no such key exists.
Returns {Key, Value} where Key is the smallest key in Tree.
Returns structural statistics about the B-tree backing Tree.
Returns {Value, Tree2} where Value is the value associated with Key
and Tree2 is Tree1 with Key removed.
Like take/2, but returns error if the key is not present instead of
raising an exception.
Returns {Key, Value, Tree2} where Key is the largest key in Tree1,
Value is its associated value, and Tree2 is Tree1 with that entry
removed.
Returns {Key, Value, Tree2} where Key is the smallest key in Tree1,
Value is its associated value, and Tree2 is Tree1 with that entry
removed.
Converts Tree into an ordered list of {Key, Value} tuples.
Unwraps an opaque tree into a plain map representation suitable for
cross-language interop (for example, converting to an Elixir struct
that uses the same underlying node module). Returns {ok, Unwrapped}
on success or {error, Reason} if Term is not a valid tree.
Updates Key to value Value in Tree1, returning a new tree Tree2.
Applies Fun to the current value of Key in Tree1, storing the
result as the new value and returning the updated tree Tree2.
Like update_with/3, but inserts Init as the value if Key is not
present in Tree1.
Returns the values in Tree as a list, ordered by their corresponding
keys.
Wraps a plain map representation back into an opaque tree.
Types
-type iter() :: iter(_, _).
Shorthand for iter(_, _).
-opaque iter(Key, Value)
An iterator over entries of type {Key, Value}. See iterator/1 and next/1.
-type tree() :: tree(_, _).
Shorthand for tree(_, _).
-opaque tree(Key, Value)
An ordered key-value tree containing entries of type {Key, Value}.
-type unwrapped_tree(Key, Value) :: #{size := non_neg_integer(), root := xb5_trees_node:t(Key, Value)}.
A plain-map representation of a tree, suitable for cross-language serialization (for example, converting to or from an Elixir struct that uses the same underlying node structures).
Functions
Returns Tree unchanged.
This function exists only to ease migration from gb_trees. Since xb5
B-trees are always balanced, calling this function is never necessary.
Examples
> T = xb5_trees:from_list([{3, c}, {1, a}, {2, b}]).
> xb5_trees:to_list(xb5_trees:balance(T)).
[{1, a}, {2, b}, {3, c}]
Removes key Key from Tree1, returning a new tree Tree2.
Raises a {badkey, Key} error if the key is not present.
Examples
> T = xb5_trees:from_list([{1, a}, {2, b}, {3, c}]).
> xb5_trees:to_list(xb5_trees:delete(2, T)).
[{1, a}, {3, c}]
Removes key Key from Tree1 if present, returning a new tree Tree2.
If Key is not present, Tree1 is returned unchanged.
Examples
> T = xb5_trees:from_list([{1, a}, {2, b}, {3, c}]).
> xb5_trees:to_list(xb5_trees:delete_any(2, T)).
[{1, a}, {3, c}]
> xb5_trees:to_list(xb5_trees:delete_any(42, T)).
[{1, a}, {2, b}, {3, c}]
-spec empty() -> tree().
Equivalent to new/0.
Inserts Key with value Value into Tree1 if the key is not present,
otherwise updates Key to value Value in Tree1.
Examples
> T0 = xb5_trees:new().
> T1 = xb5_trees:enter(1, a, T0).
> xb5_trees:to_list(T1).
[{1, a}]
> T2 = xb5_trees:enter(1, z, T1).
> xb5_trees:to_list(T2).
[{1, z}]
> T3 = xb5_trees:enter(2, b, T2).
> xb5_trees:to_list(T3).
[{1, z}, {2, b}]
-spec foldl(Function, Acc0, Tree) -> Acc1 when Function :: fun((Key, Value, AccIn) -> AccOut), Acc0 :: Acc, Acc1 :: Acc, AccIn :: Acc, AccOut :: Acc, Tree :: tree(Key, Value).
Folds Function over all entries of Tree in ascending key order,
calling Function(Key, Value, AccIn) for each entry. Returns the final
accumulator value.
Examples
> T = xb5_trees:from_list([{1, a}, {2, b}, {3, c}]).
> xb5_trees:foldl(fun(K, V, Acc) -> [{K, V} | Acc] end, [], T).
[{3, c}, {2, b}, {1, a}]
-spec foldr(Function, Acc0, Tree) -> Acc1 when Function :: fun((Key, Value, AccIn) -> AccOut), Acc0 :: Acc, Acc1 :: Acc, AccIn :: Acc, AccOut :: Acc, Tree :: tree(Key, Value).
Folds Function over all entries of Tree in descending key order,
calling Function(Key, Value, AccIn) for each entry. Returns the final
accumulator value.
Examples
> T = xb5_trees:from_list([{1, a}, {2, b}, {3, c}]).
> xb5_trees:foldr(fun(K, V, Acc) -> [{K, V} | Acc] end, [], T).
[{1, a}, {2, b}, {3, c}]
-spec from_list(List) -> Tree when List :: [{Key, Value}], Tree :: tree(Key, Value).
Returns a tree of the key-value pairs in List. Duplicate keys are
resolved by keeping the last occurrence.
It sorts the List by key and then delegates to from_orddict/1 - see that
function for performance characteristics.
Examples
> xb5_trees:to_list(xb5_trees:from_list([{3, c}, {1, a}, {2, b}])).
[{1, a}, {2, b}, {3, c}]
> xb5_trees:to_list(xb5_trees:from_list([{1, a}, {1, z}])).
[{1, z}]
> xb5_trees:to_list(xb5_trees:from_list([])).
[]
-spec from_orddict(Orddict) -> Tree when Orddict :: orddict:orddict(Key, Value), Tree :: tree(Key, Value).
Returns a tree built from the ordered dictionary Orddict.
The tree is built by recursively splitting the list top-down rather than by
sequential insertion, yielding an optimally balanced result without intermediate
allocations or element comparisons. This is analogous to gb_trees:from_orddict/1.
Examples
> xb5_trees:to_list(xb5_trees:from_orddict([{1, a}, {2, b}])).
[{1, a}, {2, b}]
-spec get(Key, Tree) -> Value when Tree :: tree(Key, Value).
Retrieves the value stored with Key in Tree.
Raises a {badkey, Key} error if the key is not present.
Examples
> T = xb5_trees:from_list([{1, a}, {2, b}, {3, c}]).
> xb5_trees:get(2, T).
b
Inserts Key with value Value into Tree1, returning a new tree
Tree2.
Raises a {key_exists, Key} error if the key is already present.
Examples
> T0 = xb5_trees:new().
> T1 = xb5_trees:insert(1, a, T0).
> xb5_trees:to_list(T1).
[{1, a}]
> T2 = xb5_trees:insert(2, b, T1).
> xb5_trees:to_list(T2).
[{1, a}, {2, b}]
-spec insert_with(Key, Fun, Tree1) -> Tree2 when Fun :: fun(() -> Value), Tree1 :: tree(Key, Value), Tree2 :: tree(Key, Value).
Like insert/3, but takes a zero-arity fun that is only evaluated when
the key is not yet present. Returns a new tree Tree2 with the key
inserted.
Raises a {key_exists, Key} error if the key already exists.
Examples
> T0 = xb5_trees:new().
> T1 = xb5_trees:insert_with(1, fun() -> a end, T0).
> xb5_trees:to_list(T1).
[{1, a}]
-spec intersect(Tree1, Tree2) -> Tree3 when Tree1 :: tree(Key, Value), Tree2 :: tree(Key, Value), Tree3 :: tree(Key, Value).
Returns the intersection of Tree1 and Tree2, i.e., a tree containing only
the keys present in both trees. For keys present in both, the value from
Tree2 is kept.
Examples
> T1 = xb5_trees:from_list([{1, a}, {2, b}, {3, c}]).
> T2 = xb5_trees:from_list([{2, x}, {3, y}, {4, z}]).
> xb5_trees:to_list(xb5_trees:intersect(T1, T2)).
[{2, x}, {3, y}]
-spec intersect_with(Fun, Tree1, Tree2) -> Tree3 when Fun :: fun((Key1 | Key2, Value1, Value2) -> Value3), Tree1 :: tree(Key1, Value1), Tree2 :: tree(Key2, Value2), Tree3 :: tree(Key1 | Key2, Value3).
Returns the intersection of Tree1 and Tree2, using Fun to compute the
value for each key present in both trees. Fun is called as
Fun(Key, Value1, Value2) where Value1 is from Tree1 and Value2 is
from Tree2.
Examples
> T1 = xb5_trees:from_list([{1, 10}, {2, 20}, {3, 30}]).
> T2 = xb5_trees:from_list([{2, 2}, {3, 3}, {4, 4}]).
> F = fun(_K, V1, V2) -> V1 * V2 end.
> xb5_trees:to_list(xb5_trees:intersect_with(F, T1, T2)).
[{2, 40}, {3, 90}]
Returns true if Key is present in Tree, otherwise false.
Examples
> T = xb5_trees:from_list([{1, a}, {2, b}, {3, c}]).
> xb5_trees:is_defined(2, T).
true
> xb5_trees:is_defined(42, T).
false
Returns true if Tree is empty, otherwise false.
Examples
> xb5_trees:is_empty(xb5_trees:new()).
true
> xb5_trees:is_empty(xb5_trees:from_list([{1, a}])).
false
Returns true if Tree1 and Tree2 contain the same keys and values, otherwise
false.
Keys are compared with ==, values with =:=.
Examples
> S1 = xb5_trees:from_list([{1, a}, {2, b}, {3, c}]).
> S2 = xb5_trees:from_list([{3, c}, {1.0, a}, {2, b}]).
> xb5_trees:is_equal(S1, S2).
true
> S3 = xb5_trees:from_list([{1, x}, {2, y}]).
> xb5_trees:is_equal(S1, S3).
false
Returns an iterator that can be used for traversing the entries of Tree;
see next/1. Equivalent to iterator(Tree, ordered).
Examples
> T = xb5_trees:from_list([{3, c}, {1, a}, {2, b}]).
> I = xb5_trees:iterator(T).
> {1, a, I2} = xb5_trees:next(I).
> {2, b, I3} = xb5_trees:next(I2).
> {3, c, I4} = xb5_trees:next(I3).
> xb5_trees:next(I4).
none
-spec iterator(Tree, Order) -> Iter when Tree :: tree(Key, Value), Iter :: iter(Key, Value), Order :: ordered | reversed.
Returns an iterator that can be used for traversing the entries of Tree
in the given Order; see next/1.
Order must be ordered (ascending) or reversed (descending).
Examples
> T = xb5_trees:from_list([{1, a}, {2, b}, {3, c}]).
> I = xb5_trees:iterator(T, reversed).
> {3, c, I2} = xb5_trees:next(I).
> {2, b, I3} = xb5_trees:next(I2).
> {1, a, I4} = xb5_trees:next(I3).
> xb5_trees:next(I4).
none
Returns an iterator that can be used for traversing the entries of Tree
starting from the first key greater than or equal to Key; see next/1.
Equivalent to iterator_from(Key, Tree, ordered).
Examples
> T = xb5_trees:from_list([{1, a}, {2, b}, {3, c}, {4, d}, {5, e}]).
> I = xb5_trees:iterator_from(3, T).
> {3, c, I2} = xb5_trees:next(I).
> {4, d, I3} = xb5_trees:next(I2).
> {5, e, I4} = xb5_trees:next(I3).
> xb5_trees:next(I4).
none
-spec iterator_from(Key, Tree, Order) -> Iter when Tree :: tree(Key, Value), Iter :: iter(Key, Value), Order :: ordered | reversed.
Returns an iterator that can be used for traversing the entries of Tree
starting from the key nearest to Key in the given Order; see next/1.
Examples
> T = xb5_trees:from_list([{1, a}, {2, b}, {3, c}, {4, d}, {5, e}]).
> I = xb5_trees:iterator_from(3, T, reversed).
> {3, c, I2} = xb5_trees:next(I).
> {2, b, I3} = xb5_trees:next(I2).
> {1, a, I4} = xb5_trees:next(I3).
> xb5_trees:next(I4).
none
-spec keys(Tree) -> [Key] when Tree :: tree(Key, _).
Returns the keys in Tree as an ordered list.
Examples
> T = xb5_trees:from_list([{3, c}, {1, a}, {2, b}]).
> xb5_trees:keys(T).
[1, 2, 3]
-spec larger(Key1, Tree) -> none | {Key2, Value} when Key1 :: Key, Key2 :: Key, Tree :: tree(Key, Value).
Returns {Key2, Value} where Key2 is the least key strictly greater
than Key1 in Tree, or none if no such key exists.
Examples
> T = xb5_trees:from_list([{1, a}, {3, c}, {5, e}]).
> xb5_trees:larger(2, T).
{3, c}
> xb5_trees:larger(5, T).
none
-spec largest(Tree) -> {Key, Value} when Tree :: tree(Key, Value).
Returns {Key, Value} where Key is the largest key in Tree.
Raises an empty_tree error if the tree is empty.
Examples
> xb5_trees:largest(xb5_trees:from_list([{1, a}, {2, b}, {3, c}])).
{3, c}
-spec lookup(Key, Tree) -> none | {value, Value} when Tree :: tree(Key, Value).
Looks up Key in Tree. Returns {value, Value} if Key is present,
or none if Key is not present.
Examples
> T = xb5_trees:from_list([{1, a}, {2, b}, {3, c}]).
> xb5_trees:lookup(2, T).
{value, b}
> xb5_trees:lookup(42, T).
none
-spec map(Function, Tree1) -> Tree2 when Function :: fun((K :: Key, V1 :: Value1) -> V2 :: Value2), Tree1 :: tree(Key, Value1), Tree2 :: tree(Key, Value2).
Maps Function over all values in Tree1, returning a new tree Tree2
with the same keys. For each entry, Function(Key, Value1) must return
the new value Value2.
Examples
> T = xb5_trees:from_list([{1, 10}, {2, 20}, {3, 30}]).
> xb5_trees:to_list(xb5_trees:map(fun(_K, V) -> V * 2 end, T)).
[{1, 20}, {2, 40}, {3, 60}]
-spec merge(Tree1, Tree2) -> Tree3 when Tree1 :: tree(KeyA, ValueA), Tree2 :: tree(KeyB, ValueB), Tree3 :: tree(KeyA | KeyB, ValueA | ValueB).
Merges Tree1 and Tree2 into a single tree. For keys present in both trees,
the value from Tree2 is kept.
Examples
> T1 = xb5_trees:from_list([{1, a}, {2, b}, {3, c}]).
> T2 = xb5_trees:from_list([{2, x}, {4, y}]).
> xb5_trees:to_list(xb5_trees:merge(T1, T2)).
[{1, a}, {2, x}, {3, c}, {4, y}]
-spec merge_with(Fun, Tree1, Tree2) -> Tree3 when Fun :: fun((KeyA | KeyB, ValueA, ValueB) -> MergeValue), Tree1 :: tree(KeyA, ValueA), Tree2 :: tree(KeyB, ValueB), Tree3 :: tree(KeyA | KeyB, ValueA | ValueB | MergeValue).
Merges Tree1 and Tree2 into a single tree, using Fun to compute the
value for each key present in both trees. Fun is called as
Fun(Key, Value1, Value2) where Value1 is from Tree1 and Value2 is
from Tree2.
Examples
> T1 = xb5_trees:from_list([{1, 10}, {2, 20}, {3, 30}]).
> T2 = xb5_trees:from_list([{2, 2}, {4, 40}]).
> F = fun(_K, V1, V2) -> V1 + V2 end.
> xb5_trees:to_list(xb5_trees:merge_with(F, T1, T2)).
[{1, 10}, {2, 22}, {3, 30}, {4, 40}]
-spec new() -> tree().
Returns a new empty tree.
Examples
> xb5_trees:is_empty(xb5_trees:new()).
true
> xb5_trees:size(xb5_trees:new()).
0
-spec next(Iter1) -> none | {Key, Value, Iter2} when Iter1 :: iter(Key, Value), Iter2 :: iter(Key, Value).
Returns {Key, Value, Iter2} where Key and Value are the next entry
referred to by iterator Iter1 and Iter2 is the updated iterator, or
none if no more entries remain.
Examples
> T = xb5_trees:from_list([{1, a}, {2, b}]).
> I = xb5_trees:iterator(T).
> {1, a, I2} = xb5_trees:next(I).
> {2, b, I3} = xb5_trees:next(I2).
> xb5_trees:next(I3).
none
-spec size(Tree) -> non_neg_integer() when Tree :: tree().
Returns the number of entries in Tree.
Examples
> xb5_trees:size(xb5_trees:new()).
0
> xb5_trees:size(xb5_trees:from_list([{1, a}, {2, b}, {3, c}])).
3
-spec smaller(Key1, Tree) -> none | {Key2, Value} when Key1 :: Key, Key2 :: Key, Tree :: tree(Key, Value).
Returns {Key2, Value} where Key2 is the greatest key strictly less
than Key1 in Tree, or none if no such key exists.
Examples
> T = xb5_trees:from_list([{1, a}, {3, c}, {5, e}]).
> xb5_trees:smaller(4, T).
{3, c}
> xb5_trees:smaller(1, T).
none
-spec smallest(Tree) -> {Key, Value} when Tree :: tree(Key, Value).
Returns {Key, Value} where Key is the smallest key in Tree.
Raises an empty_tree error if the tree is empty.
Examples
> xb5_trees:smallest(xb5_trees:from_list([{3, c}, {1, a}, {2, b}])).
{1, a}
-spec structural_stats(Tree) -> Stats when Tree :: tree(), Stats :: xb5_structural_stats:t().
Returns structural statistics about the B-tree backing Tree.
This is primarily intended for debugging and testing. The result
is a proplist with keys such as height, total_keys,
node_counts, node_percentages, and others.
Examples
> T = xb5_trees:from_list([{1, a}, {2, b}, {3, c}]).
> Stats = xb5_trees:structural_stats(T).
> {height, 1} = lists:keyfind(height, 1, Stats).
> {total_keys, 3} = lists:keyfind(total_keys, 1, Stats).
-spec take(Key, Tree1) -> {Value, Tree2} when Tree1 :: tree(Key, _), Tree2 :: tree(Key, _), Key :: term(), Value :: term().
Returns {Value, Tree2} where Value is the value associated with Key
and Tree2 is Tree1 with Key removed.
Raises a {badkey, Key} error if the key is not present.
Examples
> T = xb5_trees:from_list([{1, a}, {2, b}, {3, c}]).
> {b, T2} = xb5_trees:take(2, T).
> xb5_trees:to_list(T2).
[{1, a}, {3, c}]
-spec take_any(Key, Tree1) -> {Value, Tree2} | error when Tree1 :: tree(Key, _), Tree2 :: tree(Key, _), Key :: term(), Value :: term().
Like take/2, but returns error if the key is not present instead of
raising an exception.
Examples
> T = xb5_trees:from_list([{1, a}, {2, b}, {3, c}]).
> {b, T2} = xb5_trees:take_any(2, T).
> xb5_trees:to_list(T2).
[{1, a}, {3, c}]
> xb5_trees:take_any(42, T).
error
-spec take_largest(Tree1) -> {Key, Value, Tree2} when Tree1 :: tree(Key, Value), Tree2 :: tree(Key, Value).
Returns {Key, Value, Tree2} where Key is the largest key in Tree1,
Value is its associated value, and Tree2 is Tree1 with that entry
removed.
Raises an empty_tree error if the tree is empty.
Examples
> T = xb5_trees:from_list([{1, a}, {2, b}, {3, c}]).
> {3, c, T2} = xb5_trees:take_largest(T).
> xb5_trees:to_list(T2).
[{1, a}, {2, b}]
-spec take_smallest(Tree1) -> {Key, Value, Tree2} when Tree1 :: tree(Key, Value), Tree2 :: tree(Key, Value).
Returns {Key, Value, Tree2} where Key is the smallest key in Tree1,
Value is its associated value, and Tree2 is Tree1 with that entry
removed.
Raises an empty_tree error if the tree is empty.
Examples
> T = xb5_trees:from_list([{1, a}, {2, b}, {3, c}]).
> {1, a, T2} = xb5_trees:take_smallest(T).
> xb5_trees:to_list(T2).
[{2, b}, {3, c}]
-spec to_list(Tree) -> [{Key, Value}] when Tree :: tree(Key, Value).
Converts Tree into an ordered list of {Key, Value} tuples.
Examples
> xb5_trees:to_list(xb5_trees:from_list([{3, c}, {1, a}, {2, b}])).
[{1, a}, {2, b}, {3, c}]
> xb5_trees:to_list(xb5_trees:new()).
[]
-spec unwrap(Term :: _) -> {ok, unwrapped_tree(_, _)} | {error, Reason :: _}.
Unwraps an opaque tree into a plain map representation suitable for
cross-language interop (for example, converting to an Elixir struct
that uses the same underlying node module). Returns {ok, Unwrapped}
on success or {error, Reason} if Term is not a valid tree.
Examples
> T = xb5_trees:from_list([{1, a}, {2, b}, {3, c}]).
> {ok, Unwrapped} = xb5_trees:unwrap(T).
> maps:get(size, Unwrapped).
3
> {error, _} = xb5_trees:unwrap(not_a_tree).
Updates Key to value Value in Tree1, returning a new tree Tree2.
Raises a {badkey, Key} error if the key is not present.
Examples
> T = xb5_trees:from_list([{1, a}, {2, b}, {3, c}]).
> xb5_trees:to_list(xb5_trees:update(2, z, T)).
[{1, a}, {2, z}, {3, c}]
-spec update_with(Key, Fun, Tree1) -> Tree2 when Fun :: fun((Value1) -> Value2), Tree1 :: tree(Key, Value | Value1), Tree2 :: tree(Key, Value | Value2).
Applies Fun to the current value of Key in Tree1, storing the
result as the new value and returning the updated tree Tree2.
Raises a {badkey, Key} error if the key is not present.
Examples
> T = xb5_trees:from_list([{1, 10}, {2, 20}, {3, 30}]).
> xb5_trees:to_list(xb5_trees:update_with(2, fun(V) -> V + 1 end, T)).
[{1, 10}, {2, 21}, {3, 30}]
-spec update_with(Key, Fun, Init, Tree1) -> Tree2 when Fun :: fun((Value1) -> Value2), Tree1 :: tree(Key, Value | Value1), Tree2 :: tree(Key, Value | Value2 | Init).
Like update_with/3, but inserts Init as the value if Key is not
present in Tree1.
Examples
> T = xb5_trees:from_list([{1, 10}, {2, 20}]).
> T2 = xb5_trees:update_with(2, fun(V) -> V + 1 end, 0, T).
> xb5_trees:to_list(T2).
[{1, 10}, {2, 21}]
> T3 = xb5_trees:update_with(3, fun(V) -> V + 1 end, 0, T).
> xb5_trees:to_list(T3).
[{1, 10}, {2, 20}, {3, 0}]
-spec values(Tree) -> [Value] when Tree :: tree(_, Value).
Returns the values in Tree as a list, ordered by their corresponding
keys.
Examples
> T = xb5_trees:from_list([{3, c}, {1, a}, {2, b}]).
> xb5_trees:values(T).
[a, b, c]
-spec wrap(unwrapped_tree(Key, Value)) -> tree(Key, Value).
Wraps a plain map representation back into an opaque tree.
This is the inverse of unwrap/1 and is intended for cross-language
interop (for example, converting from an Elixir struct that shares the
same underlying node module).
Examples
> T = xb5_trees:from_list([{1, a}, {2, b}, {3, c}]).
> {ok, U} = xb5_trees:unwrap(T).
> T2 = xb5_trees:wrap(U).
> xb5_trees:to_list(T2).
[{1, a}, {2, b}, {3, c}]