1
- [ @aureooms/js-fingertree ] ( https://aureooms.github.io/js-fingertree )
1
+ : cactus : [ @aureooms/js-fingertree ] ( https://aureooms.github.io/js-fingertree )
2
2
==
3
3
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 >
5
7
6
8
Finger trees for JavaScript.
7
9
See [ docs] ( https://aureooms.github.io/js-fingertree ) .
@@ -27,7 +29,44 @@ Parent is [@aureooms/js-persistent](https://github.com/aureooms/js-persistent).
27
29
[ ![ Package size] ( https://img.shields.io/bundlephobia/minzip/@aureooms/js-fingertree )] ( https://bundlephobia.com/result?p=@aureooms/js-fingertree )
28
30
29
31
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
31
70
32
71
The data structure is
33
72
[ 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.
36
75
> The [ parent project] ( https://github.com/aureooms/js-persistent ) shows how
37
76
> specialized persistent data structures can be build on top of those methods.
38
77
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 `
50
79
51
80
data Tree x = Empty
52
81
| Single x
53
82
| Deep ( Digit x ) ( Tree ( Node x ) ) ( Digit x )
54
83
55
- ### Definition of a ` Measure `
84
+ ### : straight_ruler : Definition of a ` Measure `
56
85
57
86
Measure = (
58
87
plus = ( x , x ) -> m
59
88
measure = x -> m
60
89
zero = ( ) => m
61
90
)
62
91
63
- ### Example of a ` Measure `
92
+ #### Example of a ` Measure `
64
93
65
94
The following measure will compute the size of each subtree.
66
95
@@ -72,168 +101,210 @@ const counter = {
72
101
} ;
73
102
```
74
103
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
+ ```
76
122
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 ` :
78
125
79
126
``` js
127
+ const { from , empty } = require ( ' @aureooms/js-fingertree' ) ;
128
+ // or
80
129
import { from , empty } from ' @aureooms/js-fingertree' ;
81
130
```
82
131
83
- ### ` empty(Measure) -> Tree `
132
+ ### :baby : How to create a ` Tree `
133
+
134
+ #### ` empty(Measure) -> Tree `
84
135
85
- Create an empty fingertree from a measure object.
136
+ Create an empty tree from [ a measure object] ( #example-of-a-measure ) .
86
137
87
138
``` js
88
139
let tree = empty ( counter ) ;
89
140
```
90
141
91
- ### ` from(Measure, Iterable) -> Tree `
142
+ #### ` from(Measure, Iterable) -> Tree `
92
143
93
- Create a fingertree from a measure object and an iterable.
144
+ Create a tree from a measure object and an iterable.
94
145
95
146
``` js
96
147
let tree = from ( counter , ' abc' ) ;
97
148
```
98
149
99
- ### ` Tree#measure() -> m `
150
+ ### :question : Predicates
151
+
152
+ #### ` Tree#measure() -> m `
100
153
101
154
Returns the measure of the tree.
102
155
103
156
``` js
104
157
if ( tree .measure () > 1 ) ...
105
158
```
106
159
107
- ### ` Tree#empty() -> Boolean `
160
+ #### ` Tree#empty() -> Boolean `
108
161
109
162
Returns ` true ` if the tree is empty, ` false ` otherwise.
110
163
111
164
``` js
112
165
return tree .empty () ? ' empty' : ' not empty' ;
113
166
```
114
167
115
- ### ` Tree#head() -> x `
168
+ ### :pizza : Slice
169
+
170
+ #### ` Tree#head() -> x `
116
171
117
172
Returns the left-most value in the tree.
118
173
119
174
``` js
120
175
let head = tree .head () ; // 'a'
121
176
```
122
177
123
- ### ` Tree#last() -> x `
178
+ #### ` Tree#last() -> x `
124
179
125
180
Returns the right-most value in the tree.
126
181
127
182
``` js
128
183
let last = tree .last () ; // 'b'
129
184
```
130
185
131
- ### ` Tree#push(x ) -> Tree `
186
+ #### ` Tree#init( ) -> Tree `
132
187
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 .
134
189
135
190
``` js
136
- tree = tree .cons ( ' k ' ) ;
191
+ while ( ! tree . empty () ) tree = tree .init () ;
137
192
```
138
193
139
- ### ` Tree#cons(x ) -> Tree `
194
+ #### ` Tree#tail( ) -> Tree `
140
195
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 .
142
197
143
198
``` js
144
- tree = tree .cons ( ' g ' ) ;
199
+ while ( ! tree . empty () ) tree = tree .tail () ;
145
200
```
146
201
147
- ### ` Tree#init() -> Tree `
202
+ ### :brick: Add elements
148
203
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.
150
207
151
208
``` js
152
- while ( ! tree . empty () ) tree = tree .init () ;
209
+ tree = tree .cons ( ' k ' ) ;
153
210
```
154
211
155
- ### ` Tree#tail( ) -> Tree `
212
+ #### ` Tree#cons(x ) -> Tree `
156
213
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 .
158
215
159
216
``` js
160
- while ( ! tree . empty () ) tree = tree .tail () ;
217
+ tree = tree .cons ( ' g ' ) ;
161
218
```
162
219
163
- ### ` Tree#append(Iterable) -> Tree `
220
+ #### ` Tree#append(Iterable) -> Tree `
164
221
165
222
Equivalent to applying ` push ` to each value of the iterable in order.
166
223
167
224
``` js
168
225
tree .append ( ' www' ) ;
169
226
```
170
227
171
- ### ` Tree#prepend(Iterable) -> Tree `
228
+ #### ` Tree#prepend(Iterable) -> Tree `
172
229
173
230
Equivalent to applying ` cons ` to each value of the iterable in reverse order.
174
231
175
232
``` js
176
233
tree .prepend ( ' xyz' ) ;
177
234
```
178
235
179
- ### ` Tree#concat(Tree) -> Tree `
236
+ ### :last_quarter_moon : Merge
237
+
238
+ #### ` Tree#concat(Tree) -> Tree `
180
239
181
240
Returns the concatenation of two trees.
182
241
183
242
``` js
184
243
tree = tree .concat ( tree );
185
244
```
186
245
187
- ### ` Tree[Symbol.iterator]() -> Iterable `
188
246
189
- Returns an iterator on the values of the tree in left-to-right order.
247
+ ### : broken_heart : Split
190
248
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.
194
251
195
- ### ` Tree#splitTree(Function, m) -> [ Tree , x , Tree ] `
252
+ #### ` Tree#splitTree(Function, m) -> [ Tree , x , Tree ] `
196
253
197
254
Split the tree into a left tree, a middle value, and a right tree according to
198
255
a predicate on the measure of the tree __ increased by a constant measure ` m ` __ .
199
256
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
201
258
switches from false to true.
202
259
203
260
``` js
204
261
let [ left , right ] = tree .split ( measure => measure > 1 , 1 ) ;
205
262
```
206
263
207
- ### ` Tree#split(Function) -> [ Tree , Tree ] `
264
+ #### ` Tree#split(Function) -> [ Tree , Tree ] `
208
265
209
266
Split the tree into a left tree and a right tree according to a predicate on
210
267
the measure of the tree. The predicate must be monotone, false then true, on
211
268
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.
213
270
214
271
``` js
215
272
let [ left , right ] = tree .split ( measure => measure > 2 ) ;
216
273
```
217
274
218
- ### ` Tree#takeUntil(Function) -> Tree `
275
+ #### ` Tree#takeUntil(Function) -> Tree `
219
276
220
277
Returns the left tree of ` Tree#split ` .
221
278
222
279
``` js
223
280
let left = tree .takeUntil ( measure => measure > 2 ) ;
224
281
```
225
282
226
- ### ` Tree#dropUntil(Function) -> Tree `
283
+ #### ` Tree#dropUntil(Function) -> Tree `
227
284
228
285
Returns the right tree of ` Tree#split ` .
229
286
230
287
``` js
231
288
let right = tree .dropUntil ( measure => measure > 2 ) ;
232
289
```
233
290
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
235
304
236
305
- [ Hinze and Paterson] ( http://staff.city.ac.uk/~ross/papers/FingerTree.pdf )
306
+
307
+ ## :link : Links
237
308
- [ An (incomplete) implementation in Python] ( https://github.com/kachayev/fn.py/blob/main/fn/immutable/finger.py )
238
309
- [ A (buggy) previous JavaScript implementation] ( https://github.com/qiao/fingertree.js )
239
310
- [ A coffeescript implementation] ( https://github.com/zot/Leisure/blob/main/src/lib/fingertree.coffee )
0 commit comments