Skip to content

Commit a489167

Browse files
committed
update some docs
1 parent 6a29095 commit a489167

File tree

2 files changed

+43
-26
lines changed

2 files changed

+43
-26
lines changed

src/internal/disjoint_set.gleam

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
import gleam/dict
22
import gleam/list
3+
import gleam/pair
34

45
pub opaque type DisjointSet(a) {
56
DisjointSet(parents: dict.Dict(a, a), sizes: dict.Dict(a, Int))
67
}
78

9+
/// Create a disjoint set from a list of items. Initially all items are
10+
/// separate sets.
811
pub fn from_list(items: List(a)) -> DisjointSet(a) {
912
let #(parents, sizes) =
1013
list.fold(items, #(dict.new(), dict.new()), fn(acc, item) {
@@ -13,6 +16,9 @@ pub fn from_list(items: List(a)) -> DisjointSet(a) {
1316
DisjointSet(parents:, sizes:)
1417
}
1518

19+
/// Find the set to which an item belogs. This will return an updated
20+
/// copy of the disjoint set with some path optimization and the root
21+
/// element defining the set.
1622
pub fn find(dj: DisjointSet(a), item: a) -> Result(#(DisjointSet(a), a), Nil) {
1723
case dict.get(dj.parents, item) {
1824
Ok(parent) -> {
@@ -22,13 +28,13 @@ pub fn find(dj: DisjointSet(a), item: a) -> Result(#(DisjointSet(a), a), Nil) {
2228
// Path compression to make each item point to a single representative set parent
2329
case find(dj, parent) {
2430
Error(_) -> Error(Nil)
25-
Ok(#(dj, rep_parent)) -> {
31+
Ok(#(dj, root)) -> {
2632
let updated_dj =
2733
DisjointSet(
28-
parents: dict.insert(dj.parents, item, rep_parent),
34+
parents: dict.insert(dj.parents, item, root),
2935
sizes: dj.sizes,
3036
)
31-
Ok(#(updated_dj, rep_parent))
37+
Ok(#(updated_dj, root))
3238
}
3339
}
3440
}
@@ -38,6 +44,10 @@ pub fn find(dj: DisjointSet(a), item: a) -> Result(#(DisjointSet(a), a), Nil) {
3844
}
3945
}
4046

47+
/// Create a union set from the set containing the element x
48+
/// and the set containing the element y. If they are already
49+
/// in the same set nothing happens. This returns an updated
50+
/// disjoint set.
4151
pub fn union(dj: DisjointSet(a), x: a, y: a) -> Result(DisjointSet(a), Nil) {
4252
case find(dj, x) {
4353
Error(Nil) -> Error(Nil)
@@ -67,13 +77,15 @@ pub fn union(dj: DisjointSet(a), x: a, y: a) -> Result(DisjointSet(a), Nil) {
6777
}
6878
}
6979

80+
/// Find the size of the set which contains item.
7081
pub fn size(dj: DisjointSet(a), item: a) -> Result(Int, Nil) {
7182
case find(dj, item) {
7283
Error(Nil) -> Error(Nil)
7384
Ok(#(dj, rep_parent)) -> dict.get(dj.sizes, rep_parent)
7485
}
7586
}
7687

88+
// I am thinking about just providing all sets
7789
pub fn to_list(dj: DisjointSet(a), item: a) -> Result(List(a), Nil) {
7890
case find(dj, item) {
7991
Error(Nil) -> Error(Nil)
@@ -91,11 +103,7 @@ pub fn to_list(dj: DisjointSet(a), item: a) -> Result(List(a), Nil) {
91103
}
92104

93105
pub fn setlist(dj: DisjointSet(a)) -> List(a) {
94-
dict.keys(dj.parents)
95-
|> list.filter(fn(item) {
96-
case find(dj, item) {
97-
Ok(#(_, p)) if p == item -> True
98-
_ -> False
99-
}
100-
})
106+
dict.to_list(dj.parents)
107+
|> list.filter(fn(pair) { pair.0 == pair.1 })
108+
|> list.map(pair.first)
101109
}

src/internal/memoize.gleam

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,20 @@
1+
//// Memoization in Gleam threw me for a loop, but an actor can hold
2+
//// the information I need. Below are the building blocks of an
3+
//// actor that holds a dict with a stone number and generations as
4+
//// a key, and the total count of stones will be descended from it
5+
//// after than many generations.
6+
17
import gleam/dict.{type Dict}
28
import gleam/erlang/process.{type Subject}
39
import gleam/otp/actor
410

5-
// Memoization in Gleam threw me for a loop, but an actor can hold
6-
// the information I need. Below are the building blocks of an
7-
// actor that holds a dict with a stone number and generations as
8-
// a key, and the total count of stones will be descended from it
9-
// after than many generations.
10-
1111
pub type Message(a, b) {
1212
Put(key: a, value: b)
1313
Get(reply_with: Subject(Result(b, Nil)), key: a)
1414
Shutdown
1515
}
1616

17+
/// A memoization cache. The state is held in an actor.
1718
pub type Cache(a, b) =
1819
Subject(Message(a, b))
1920

@@ -28,12 +29,16 @@ pub fn handle_message(current: Dict(a, b), message: Message(a, b)) {
2829
}
2930
}
3031

31-
// To check a cache first for a result first, before the rest of the function
32-
// runs add
33-
// use <- cache_check(cache, #(param1, param2, ...))
34-
// It will look up those parameters in the cache and return a value if found.
35-
// otherwise it continues with the function and records the response for those
36-
// parameters.
32+
/// To check a cache first for a result first, before the rest of the function
33+
/// runs add
34+
///
35+
/// ```gleam
36+
/// use <- cache_check(cache, #(param1, param2, ...))
37+
/// ```
38+
///
39+
/// It will look up those parameters in the cache and return a value if found.
40+
/// otherwise it continues with the function and records the response for those
41+
/// parameters.
3742
pub fn cache_check(cache: Cache(a, b), key: a, callback: fn() -> b) -> b {
3843
let cache_result = process.call(cache, 100, Get(_, key))
3944

@@ -60,10 +65,14 @@ pub fn cache_shutdown(cache: Cache(a, b)) {
6065
process.send(cache, Shutdown)
6166
}
6267

63-
// To initialize a cache for the rest of a function, add
64-
// use cache <- with_cache()
65-
// to the function. The rest of the function is a callback
66-
// with an actor holding the cache.
68+
/// To initialize a cache for the rest of a function, add
69+
///
70+
/// ```gleam
71+
/// use cache <- with_cache()
72+
/// ```
73+
///
74+
/// to the function. The rest of the function is a callback
75+
/// with an actor holding the cache.
6776
pub fn with_cache(callback: fn(Cache(a, b)) -> c) -> c {
6877
let cache = cache_init()
6978

0 commit comments

Comments
 (0)