Skip to content

Commit a08af63

Browse files
📚 docs(README): Improve.
- Add emojis - Reduce header image size - Add TOC - Curate text - Curate hierarchy
1 parent 6eb2e90 commit a08af63

File tree

1 file changed

+124
-53
lines changed

1 file changed

+124
-53
lines changed

README.md

Lines changed: 124 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1-
[@aureooms/js-fingertree](https://aureooms.github.io/js-fingertree)
1+
:cactus: [@aureooms/js-fingertree](https://aureooms.github.io/js-fingertree)
22
==
33

4-
<img src="https://cdn.rawgit.com/aureooms/js-fingertree/main/media/sketch.svg" width="864">
4+
<p align="center">
5+
<img src="https://cdn.rawgit.com/aureooms/js-fingertree/main/media/sketch.svg" width="400">
6+
</p>
57

68
Finger trees for JavaScript.
79
See [docs](https://aureooms.github.io/js-fingertree).
@@ -27,7 +29,44 @@ Parent is [@aureooms/js-persistent](https://github.com/aureooms/js-persistent).
2729
[![Package size](https://img.shields.io/bundlephobia/minzip/@aureooms/js-fingertree)](https://bundlephobia.com/result?p=@aureooms/js-fingertree)
2830

2931

30-
## API reference
32+
<!-- vim-markdown-toc GFM -->
33+
34+
* [:woman_teacher: API reference](#woman_teacher-api-reference)
35+
* [:cactus: Definition of a `Tree`](#cactus-definition-of-a-tree)
36+
* [:straight_ruler: Definition of a `Measure`](#straight_ruler-definition-of-a-measure)
37+
* [Example of a `Measure`](#example-of-a-measure)
38+
* [:package: How to `import`](#package-how-to-import)
39+
* [:baby: How to create a `Tree`](#baby-how-to-create-a-tree)
40+
* [`empty(Measure) -> Tree`](#emptymeasure---tree)
41+
* [`from(Measure, Iterable) -> Tree`](#frommeasure-iterable---tree)
42+
* [:question: Predicates](#question-predicates)
43+
* [`Tree#measure() -> m`](#treemeasure---m)
44+
* [`Tree#empty() -> Boolean`](#treeempty---boolean)
45+
* [:pizza: Slice](#pizza-slice)
46+
* [`Tree#head() -> x`](#treehead---x)
47+
* [`Tree#last() -> x`](#treelast---x)
48+
* [`Tree#init() -> Tree`](#treeinit---tree)
49+
* [`Tree#tail() -> Tree`](#treetail---tree)
50+
* [:brick: Add elements](#brick-add-elements)
51+
* [`Tree#push(x) -> Tree`](#treepushx---tree)
52+
* [`Tree#cons(x) -> Tree`](#treeconsx---tree)
53+
* [`Tree#append(Iterable) -> Tree`](#treeappenditerable---tree)
54+
* [`Tree#prepend(Iterable) -> Tree`](#treeprependiterable---tree)
55+
* [:last_quarter_moon: Merge](#last_quarter_moon-merge)
56+
* [`Tree#concat(Tree) -> Tree`](#treeconcattree---tree)
57+
* [:broken_heart: Split](#broken_heart-split)
58+
* [`Tree#splitTree(Function, m) -> [ Tree , x , Tree ]`](#treesplittreefunction-m----tree--x--tree-)
59+
* [`Tree#split(Function) -> [ Tree , Tree ]`](#treesplitfunction----tree--tree-)
60+
* [`Tree#takeUntil(Function) -> Tree`](#treetakeuntilfunction---tree)
61+
* [`Tree#dropUntil(Function) -> Tree`](#treedropuntilfunction---tree)
62+
* [:flying_saucer: Visit](#flying_saucer-visit)
63+
* [`TreeSymbol.iterator -> Iterable`](#treesymboliterator---iterable)
64+
* [:scroll: References](#scroll-references)
65+
* [:link: Links](#link-links)
66+
67+
<!-- vim-markdown-toc -->
68+
69+
## :woman_teacher: API reference
3170

3271
The data structure is
3372
[fully persistent](https://en.wikipedia.org/wiki/Persistent_data_structure#Fully_persistent):
@@ -36,31 +75,21 @@ All methods are pure functions that do not modify their object.
3675
> The [parent project](https://github.com/aureooms/js-persistent) shows how
3776
> specialized persistent data structures can be build on top of those methods.
3877
39-
> :warning: The code requires `regeneratorRuntime` to be defined, for instance by importing
40-
> [regenerator-runtime/runtime](https://www.npmjs.com/package/regenerator-runtime).
41-
42-
First, require the polyfill at the entry point of your application
43-
```js
44-
require( 'regenerator-runtime/runtime' );
45-
// or
46-
import 'regenerator-runtime/runtime.js' ;
47-
```
48-
49-
### Definition of a `Tree`
78+
### :cactus: Definition of a `Tree`
5079

5180
data Tree x = Empty
5281
| Single x
5382
| Deep ( Digit x ) ( Tree ( Node x ) ) ( Digit x )
5483

55-
### Definition of a `Measure`
84+
### :straight_ruler: Definition of a `Measure`
5685

5786
Measure = (
5887
plus = ( x , x ) -> m
5988
measure = x -> m
6089
zero = ( ) => m
6190
)
6291

63-
### Example of a `Measure`
92+
#### Example of a `Measure`
6493

6594
The following measure will compute the size of each subtree.
6695

@@ -72,168 +101,210 @@ const counter = {
72101
} ;
73102
```
74103

75-
### How to `import`
104+
See also
105+
[@aureooms/js-measure](https://aureooms.github.io/js-measure/file/src/1-api/1-Measures.js.html)
106+
for more examples of measures and see
107+
[@aureooms/js-persistent](https://github.com/aureooms/js-persistent)
108+
for examples of data structures that can be build on top of this abstraction.
109+
110+
111+
### :package: How to `import`
112+
113+
> :warning: The code requires `regeneratorRuntime` to be defined, for instance by importing
114+
> [regenerator-runtime/runtime](https://www.npmjs.com/package/regenerator-runtime).
115+
116+
First, require the polyfill at the entry point of your application:
117+
```js
118+
require( 'regenerator-runtime/runtime' ) ;
119+
// or
120+
import 'regenerator-runtime/runtime.js' ;
121+
```
76122

77-
No surprises here:
123+
Then require what you need from the exported object, for instance the two main
124+
API functions `from` and `empty`:
78125

79126
```js
127+
const { from , empty } = require( '@aureooms/js-fingertree' ) ;
128+
// or
80129
import { from , empty } from '@aureooms/js-fingertree' ;
81130
```
82131

83-
### `empty(Measure) -> Tree`
132+
### :baby: How to create a `Tree`
133+
134+
#### `empty(Measure) -> Tree`
84135

85-
Create an empty fingertree from a measure object.
136+
Create an empty tree from [a measure object](#example-of-a-measure).
86137

87138
```js
88139
let tree = empty( counter ) ;
89140
```
90141

91-
### `from(Measure, Iterable) -> Tree`
142+
#### `from(Measure, Iterable) -> Tree`
92143

93-
Create a fingertree from a measure object and an iterable.
144+
Create a tree from a measure object and an iterable.
94145

95146
```js
96147
let tree = from( counter , 'abc' ) ;
97148
```
98149

99-
### `Tree#measure() -> m`
150+
### :question: Predicates
151+
152+
#### `Tree#measure() -> m`
100153

101154
Returns the measure of the tree.
102155

103156
```js
104157
if ( tree.measure() > 1 ) ...
105158
```
106159

107-
### `Tree#empty() -> Boolean`
160+
#### `Tree#empty() -> Boolean`
108161

109162
Returns `true` if the tree is empty, `false` otherwise.
110163

111164
```js
112165
return tree.empty() ? 'empty' : 'not empty' ;
113166
```
114167

115-
### `Tree#head() -> x`
168+
### :pizza: Slice
169+
170+
#### `Tree#head() -> x`
116171

117172
Returns the left-most value in the tree.
118173

119174
```js
120175
let head = tree.head() ; // 'a'
121176
```
122177

123-
### `Tree#last() -> x`
178+
#### `Tree#last() -> x`
124179

125180
Returns the right-most value in the tree.
126181

127182
```js
128183
let last = tree.last() ; // 'b'
129184
```
130185

131-
### `Tree#push(x) -> Tree`
186+
#### `Tree#init() -> Tree`
132187

133-
Returns a new tree with an additional value as the new right-most value.
188+
Returns a new tree without the right-most element.
134189

135190
```js
136-
tree = tree.cons('k');
191+
while ( ! tree.empty() ) tree = tree.init() ;
137192
```
138193

139-
### `Tree#cons(x) -> Tree`
194+
#### `Tree#tail() -> Tree`
140195

141-
Returns a new tree with an additional value as the new left-most value.
196+
Returns a new tree without the left-most element.
142197

143198
```js
144-
tree = tree.cons('g');
199+
while ( ! tree.empty() ) tree = tree.tail() ;
145200
```
146201

147-
### `Tree#init() -> Tree`
202+
### :brick: Add elements
148203

149-
Returns a new tree without the right-most element.
204+
#### `Tree#push(x) -> Tree`
205+
206+
Returns a new tree with an additional value as the new right-most value.
150207

151208
```js
152-
while ( ! tree.empty() ) tree = tree.init() ;
209+
tree = tree.cons('k');
153210
```
154211

155-
### `Tree#tail() -> Tree`
212+
#### `Tree#cons(x) -> Tree`
156213

157-
Returns a new tree without the left-most element.
214+
Returns a new tree with an additional value as the new left-most value.
158215

159216
```js
160-
while ( ! tree.empty() ) tree = tree.tail() ;
217+
tree = tree.cons('g');
161218
```
162219

163-
### `Tree#append(Iterable) -> Tree`
220+
#### `Tree#append(Iterable) -> Tree`
164221

165222
Equivalent to applying `push` to each value of the iterable in order.
166223

167224
```js
168225
tree.append( 'www' ) ;
169226
```
170227

171-
### `Tree#prepend(Iterable) -> Tree`
228+
#### `Tree#prepend(Iterable) -> Tree`
172229

173230
Equivalent to applying `cons` to each value of the iterable in reverse order.
174231

175232
```js
176233
tree.prepend( 'xyz' ) ;
177234
```
178235

179-
### `Tree#concat(Tree) -> Tree`
236+
### :last_quarter_moon: Merge
237+
238+
#### `Tree#concat(Tree) -> Tree`
180239

181240
Returns the concatenation of two trees.
182241

183242
```js
184243
tree = tree.concat( tree );
185244
```
186245

187-
### `Tree[Symbol.iterator]() -> Iterable`
188246

189-
Returns an iterator on the values of the tree in left-to-right order.
247+
### :broken_heart: Split
190248

191-
```js
192-
for ( const x of tree ) console.log( x ) ;
193-
```
249+
The following methods allow you to efficiently split a tree at the element
250+
where the measure crosses a given threshold.
194251

195-
### `Tree#splitTree(Function, m) -> [ Tree , x , Tree ]`
252+
#### `Tree#splitTree(Function, m) -> [ Tree , x , Tree ]`
196253

197254
Split the tree into a left tree, a middle value, and a right tree according to
198255
a predicate on the measure of the tree __increased by a constant measure `m`__.
199256
The predicate must be monotone, false then true, on prefixes of the values in
200-
left-to-right order. The middle value `x` is the item for which the predicate
257+
left-to-right order. The middle value `x` is the element for which the predicate
201258
switches from false to true.
202259

203260
```js
204261
let [ left , right ] = tree.split( measure => measure > 1 , 1 ) ;
205262
```
206263

207-
### `Tree#split(Function) -> [ Tree , Tree ]`
264+
#### `Tree#split(Function) -> [ Tree , Tree ]`
208265

209266
Split the tree into a left tree and a right tree according to a predicate on
210267
the measure of the tree. The predicate must be monotone, false then true, on
211268
prefixes of the values in left-to-right order. The left-most value of the right
212-
tree is the item for which the predicate switches from false to true.
269+
tree is the element for which the predicate switches from false to true.
213270

214271
```js
215272
let [ left , right ] = tree.split( measure => measure > 2 ) ;
216273
```
217274

218-
### `Tree#takeUntil(Function) -> Tree`
275+
#### `Tree#takeUntil(Function) -> Tree`
219276

220277
Returns the left tree of `Tree#split`.
221278

222279
```js
223280
let left = tree.takeUntil( measure => measure > 2 ) ;
224281
```
225282

226-
### `Tree#dropUntil(Function) -> Tree`
283+
#### `Tree#dropUntil(Function) -> Tree`
227284

228285
Returns the right tree of `Tree#split`.
229286

230287
```js
231288
let right = tree.dropUntil( measure => measure > 2 ) ;
232289
```
233290

234-
## References
291+
292+
### :flying_saucer: Visit
293+
294+
#### `Tree[Symbol.iterator]() -> Iterable`
295+
296+
Returns an iterator on the values of the tree in left-to-right order.
297+
298+
```js
299+
for ( const x of tree ) console.log( x ) ;
300+
```
301+
302+
303+
## :scroll: References
235304

236305
- [Hinze and Paterson](http://staff.city.ac.uk/~ross/papers/FingerTree.pdf)
306+
307+
## :link: Links
237308
- [An (incomplete) implementation in Python](https://github.com/kachayev/fn.py/blob/main/fn/immutable/finger.py)
238309
- [A (buggy) previous JavaScript implementation](https://github.com/qiao/fingertree.js)
239310
- [A coffeescript implementation](https://github.com/zot/Leisure/blob/main/src/lib/fingertree.coffee)

0 commit comments

Comments
 (0)