@grain/stdlib 0.5.13 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +193 -0
- package/LICENSE +1 -1
- package/README.md +25 -2
- package/array.gr +1512 -199
- package/array.md +2032 -94
- package/bigint.gr +239 -140
- package/bigint.md +450 -106
- package/buffer.gr +595 -102
- package/buffer.md +903 -145
- package/bytes.gr +401 -110
- package/bytes.md +551 -63
- package/char.gr +228 -49
- package/char.md +373 -7
- package/exception.gr +26 -12
- package/exception.md +29 -5
- package/float32.gr +130 -109
- package/float32.md +185 -57
- package/float64.gr +112 -99
- package/float64.md +185 -57
- package/hash.gr +47 -37
- package/hash.md +21 -3
- package/int16.gr +430 -0
- package/int16.md +618 -0
- package/int32.gr +200 -269
- package/int32.md +254 -289
- package/int64.gr +142 -225
- package/int64.md +254 -289
- package/int8.gr +511 -0
- package/int8.md +786 -0
- package/json.gr +2084 -0
- package/json.md +608 -0
- package/list.gr +120 -68
- package/list.md +125 -80
- package/map.gr +560 -57
- package/map.md +672 -56
- package/marshal.gr +239 -227
- package/marshal.md +36 -4
- package/number.gr +626 -676
- package/number.md +738 -153
- package/option.gr +33 -35
- package/option.md +58 -42
- package/package.json +2 -2
- package/path.gr +148 -187
- package/path.md +47 -96
- package/pervasives.gr +75 -416
- package/pervasives.md +85 -180
- package/priorityqueue.gr +433 -74
- package/priorityqueue.md +422 -54
- package/queue.gr +362 -80
- package/queue.md +433 -38
- package/random.gr +67 -75
- package/random.md +68 -40
- package/range.gr +135 -63
- package/range.md +198 -43
- package/rational.gr +284 -0
- package/rational.md +545 -0
- package/regex.gr +933 -1066
- package/regex.md +59 -60
- package/result.gr +23 -25
- package/result.md +54 -39
- package/runtime/atof/common.gr +78 -82
- package/runtime/atof/common.md +22 -10
- package/runtime/atof/decimal.gr +102 -127
- package/runtime/atof/decimal.md +28 -7
- package/runtime/atof/lemire.gr +56 -71
- package/runtime/atof/lemire.md +9 -1
- package/runtime/atof/parse.gr +83 -110
- package/runtime/atof/parse.md +12 -2
- package/runtime/atof/slow.gr +28 -35
- package/runtime/atof/slow.md +9 -1
- package/runtime/atof/table.gr +19 -18
- package/runtime/atof/table.md +10 -2
- package/runtime/atoi/parse.gr +153 -136
- package/runtime/atoi/parse.md +50 -1
- package/runtime/bigint.gr +410 -517
- package/runtime/bigint.md +71 -57
- package/runtime/compare.gr +176 -85
- package/runtime/compare.md +31 -1
- package/runtime/dataStructures.gr +144 -32
- package/runtime/dataStructures.md +267 -31
- package/runtime/debugPrint.gr +34 -15
- package/runtime/debugPrint.md +37 -5
- package/runtime/equal.gr +53 -52
- package/runtime/equal.md +30 -1
- package/runtime/exception.gr +38 -47
- package/runtime/exception.md +10 -8
- package/runtime/gc.gr +23 -152
- package/runtime/gc.md +13 -17
- package/runtime/malloc.gr +31 -31
- package/runtime/malloc.md +11 -3
- package/runtime/numberUtils.gr +191 -172
- package/runtime/numberUtils.md +17 -9
- package/runtime/numbers.gr +1695 -1021
- package/runtime/numbers.md +1098 -134
- package/runtime/string.gr +540 -242
- package/runtime/string.md +76 -6
- package/runtime/unsafe/constants.gr +30 -13
- package/runtime/unsafe/constants.md +80 -0
- package/runtime/unsafe/conv.gr +55 -28
- package/runtime/unsafe/conv.md +41 -9
- package/runtime/unsafe/memory.gr +10 -30
- package/runtime/unsafe/memory.md +15 -19
- package/runtime/unsafe/tags.gr +37 -21
- package/runtime/unsafe/tags.md +88 -8
- package/runtime/unsafe/wasmf32.gr +30 -36
- package/runtime/unsafe/wasmf32.md +64 -56
- package/runtime/unsafe/wasmf64.gr +30 -36
- package/runtime/unsafe/wasmf64.md +64 -56
- package/runtime/unsafe/wasmi32.gr +49 -66
- package/runtime/unsafe/wasmi32.md +102 -94
- package/runtime/unsafe/wasmi64.gr +52 -79
- package/runtime/unsafe/wasmi64.md +108 -100
- package/runtime/utils/printing.gr +13 -15
- package/runtime/utils/printing.md +11 -3
- package/runtime/wasi.gr +294 -295
- package/runtime/wasi.md +62 -42
- package/set.gr +574 -64
- package/set.md +634 -54
- package/stack.gr +181 -64
- package/stack.md +271 -42
- package/string.gr +453 -533
- package/string.md +241 -151
- package/uint16.gr +369 -0
- package/uint16.md +585 -0
- package/uint32.gr +470 -0
- package/uint32.md +737 -0
- package/uint64.gr +471 -0
- package/uint64.md +737 -0
- package/uint8.gr +369 -0
- package/uint8.md +585 -0
- package/uri.gr +1093 -0
- package/uri.md +477 -0
- package/{sys → wasi}/file.gr +914 -500
- package/{sys → wasi}/file.md +454 -50
- package/wasi/process.gr +292 -0
- package/{sys → wasi}/process.md +164 -6
- package/wasi/random.gr +77 -0
- package/wasi/random.md +80 -0
- package/{sys → wasi}/time.gr +15 -22
- package/{sys → wasi}/time.md +5 -5
- package/immutablearray.gr +0 -929
- package/immutablearray.md +0 -1038
- package/immutablemap.gr +0 -493
- package/immutablemap.md +0 -479
- package/immutablepriorityqueue.gr +0 -360
- package/immutablepriorityqueue.md +0 -291
- package/immutableset.gr +0 -498
- package/immutableset.md +0 -449
- package/runtime/debug.gr +0 -2
- package/runtime/debug.md +0 -6
- package/runtime/unsafe/errors.gr +0 -36
- package/runtime/unsafe/errors.md +0 -204
- package/sys/process.gr +0 -254
- package/sys/random.gr +0 -79
- package/sys/random.md +0 -66
package/immutableset.gr
DELETED
|
@@ -1,498 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @module ImmutableSet: An ImmutableSet is a collection of unique values. Operations on an ImmutableSet do not mutate the set's internal state.
|
|
3
|
-
* @example import ImmutableSet from "immutableset"
|
|
4
|
-
*
|
|
5
|
-
* @since v0.5.4
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import List from "list"
|
|
9
|
-
import Array from "array"
|
|
10
|
-
|
|
11
|
-
// implementation based on the paper "Implementing Sets Efficiently in a
|
|
12
|
-
// Functional Language" by Stephen Adams
|
|
13
|
-
|
|
14
|
-
record Node<a> {
|
|
15
|
-
key: a,
|
|
16
|
-
size: Number,
|
|
17
|
-
left: ImmutableSet<a>,
|
|
18
|
-
right: ImmutableSet<a>,
|
|
19
|
-
},
|
|
20
|
-
/**
|
|
21
|
-
* @section Types: Type declarations included in the ImmutableSet module.
|
|
22
|
-
*/
|
|
23
|
-
enum ImmutableSet<a> {
|
|
24
|
-
Empty,
|
|
25
|
-
Tree(Node<a>),
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* @section Values: Functions and constants for working with ImmutableSets.
|
|
30
|
-
*/
|
|
31
|
-
|
|
32
|
-
// semi-arbitrary value chosen for algorithm for determining when to balance
|
|
33
|
-
// trees; no tree can have a left subtree containing this number of times
|
|
34
|
-
// more elements than its right subtree or vice versa
|
|
35
|
-
let weight = 4
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* An empty set
|
|
39
|
-
*
|
|
40
|
-
* @since v0.5.4
|
|
41
|
-
*/
|
|
42
|
-
export let empty = Empty
|
|
43
|
-
|
|
44
|
-
// returns the minimum value in a tree
|
|
45
|
-
let rec min = node => {
|
|
46
|
-
match (node) {
|
|
47
|
-
Tree({ key, left: Empty, _ }) => key,
|
|
48
|
-
Tree({ left, _ }) => min(left),
|
|
49
|
-
Empty => fail "Impossible: min of empty element in ImmutableSet",
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Provides the count of values within the set.
|
|
55
|
-
*
|
|
56
|
-
* @param set: The set to inspect
|
|
57
|
-
* @returns The count of elements in the set
|
|
58
|
-
*
|
|
59
|
-
* @since v0.5.4
|
|
60
|
-
*/
|
|
61
|
-
export let size = set => {
|
|
62
|
-
match (set) {
|
|
63
|
-
Empty => 0,
|
|
64
|
-
Tree({ size, _ }) => size,
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* Determines if the set contains no elements.
|
|
70
|
-
*
|
|
71
|
-
* @param set: The set to inspect
|
|
72
|
-
* @returns `true` if the given set is empty or `false` otherwise
|
|
73
|
-
*
|
|
74
|
-
* @since v0.5.4
|
|
75
|
-
*/
|
|
76
|
-
export let isEmpty = set => {
|
|
77
|
-
match (set) {
|
|
78
|
-
Empty => true,
|
|
79
|
-
Tree(_) => false,
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
let unwrapTree = node => {
|
|
84
|
-
match (node) {
|
|
85
|
-
Empty => fail "Impossible: ImmutableSet unwrapTree got an empty tree node",
|
|
86
|
-
Tree(tree) => tree,
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
// helper function for creating a tree node with correct size from
|
|
91
|
-
// two balanced trees
|
|
92
|
-
let makeNode = (key, left, right) => {
|
|
93
|
-
Tree({ key, size: 1 + size(left) + size(right), left, right })
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
// note: see Figure 1 of paper referenced above for visual illustration of
|
|
97
|
-
// the rotations below
|
|
98
|
-
|
|
99
|
-
// node rotation moving the left subtree of the right node to the left side
|
|
100
|
-
let singleL = (key, left, right) => {
|
|
101
|
-
let { key: rKey, left: rl, right: rr, _ } = unwrapTree(right)
|
|
102
|
-
makeNode(rKey, makeNode(key, left, rl), rr)
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
// node rotation moving left child of right tree to the root
|
|
106
|
-
let doubleL = (key, left, right) => {
|
|
107
|
-
let { key: rKey, left: rl, right: rr, _ } = unwrapTree(right)
|
|
108
|
-
let { key: rlKey, left: rll, right: rlr, _ } = unwrapTree(rl)
|
|
109
|
-
makeNode(rlKey, makeNode(key, left, rll), makeNode(rKey, rlr, rr))
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
// node rotation moving the right subtree of the left node to the right side
|
|
113
|
-
let singleR = (key, left, right) => {
|
|
114
|
-
let { key: lKey, left: ll, right: lr, _ } = unwrapTree(left)
|
|
115
|
-
makeNode(lKey, ll, makeNode(key, lr, right))
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
// node rotation moving right child of left tree to the root
|
|
119
|
-
let doubleR = (key, left, right) => {
|
|
120
|
-
let { key: lKey, left: ll, right: lr, _ } = unwrapTree(left)
|
|
121
|
-
let { key: lrKey, left: lrl, right: lrr, _ } = unwrapTree(lr)
|
|
122
|
-
makeNode(lrKey, makeNode(lKey, ll, lrl), makeNode(key, lrr, right))
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
// creates a new node after either the left or right trees have just had an
|
|
126
|
-
// element inserted or removed from them, maintaining balance in the tree
|
|
127
|
-
let balancedNode = (key, left, right) => {
|
|
128
|
-
let makeNodeFn = if (size(left) + size(right) < 2) {
|
|
129
|
-
makeNode
|
|
130
|
-
} else if (size(right) > weight * size(left)) {
|
|
131
|
-
// if the right tree is too much larger than the left then move part of
|
|
132
|
-
// the right tree to the left side
|
|
133
|
-
let { left: rl, right: rr, _ } = unwrapTree(right)
|
|
134
|
-
if (size(rl) < size(rr)) singleL else doubleL
|
|
135
|
-
} else if (size(left) > weight * size(right)) {
|
|
136
|
-
// if the left tree is too much larger than the right then move part of
|
|
137
|
-
// the left tree to the right side
|
|
138
|
-
let { left: ll, right: lr, _ } = unwrapTree(left)
|
|
139
|
-
if (size(lr) < size(ll)) singleR else doubleR
|
|
140
|
-
} else {
|
|
141
|
-
// if neither tree is too much larger than the other then simply create
|
|
142
|
-
// a new node
|
|
143
|
-
makeNode
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
makeNodeFn(key, left, right)
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
/**
|
|
150
|
-
* Produces a new set by inserting the given value into the set. If the value
|
|
151
|
-
* already exists, the new set will have the same elements as the input set.
|
|
152
|
-
*
|
|
153
|
-
* @param key: The value to add
|
|
154
|
-
* @param set: The base set
|
|
155
|
-
* @returns A new set containing the new element
|
|
156
|
-
*
|
|
157
|
-
* @since v0.5.4
|
|
158
|
-
*/
|
|
159
|
-
export let rec add = (key, set) => {
|
|
160
|
-
match (set) {
|
|
161
|
-
Empty => Tree({ key, size: 1, left: Empty, right: Empty }),
|
|
162
|
-
Tree({ key: nodeKey, left, right, _ }) => {
|
|
163
|
-
match (compare(key, nodeKey)) {
|
|
164
|
-
cmp when cmp < 0 => balancedNode(nodeKey, add(key, left), right),
|
|
165
|
-
cmp when cmp > 0 => balancedNode(nodeKey, left, add(key, right)),
|
|
166
|
-
_ => makeNode(key, left, right),
|
|
167
|
-
}
|
|
168
|
-
},
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
/**
|
|
173
|
-
* Determines if the set contains the given value.
|
|
174
|
-
*
|
|
175
|
-
* @param key: The value to search for
|
|
176
|
-
* @param set: The set to search
|
|
177
|
-
* @returns `true` if the set contains the given value or `false` otherwise
|
|
178
|
-
*
|
|
179
|
-
* @since v0.5.4
|
|
180
|
-
*/
|
|
181
|
-
export let rec contains = (key, set) => {
|
|
182
|
-
match (set) {
|
|
183
|
-
Empty => false,
|
|
184
|
-
Tree({ key: nodeKey, left, right, _ }) => {
|
|
185
|
-
match (compare(key, nodeKey)) {
|
|
186
|
-
cmp when cmp < 0 => contains(key, left),
|
|
187
|
-
cmp when cmp > 0 => contains(key, right),
|
|
188
|
-
_ => true,
|
|
189
|
-
}
|
|
190
|
-
},
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
// removes the minimum element from a tree
|
|
195
|
-
let rec removeMin = node => {
|
|
196
|
-
match (node) {
|
|
197
|
-
Tree({ left: Empty, right, _ }) => right,
|
|
198
|
-
Tree({ key, left, right, _ }) => balancedNode(key, removeMin(left), right),
|
|
199
|
-
_ => fail "Impossible: ImmutableSet removeMin on empty node",
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
// helper function for removing a node by creating a new node containing the
|
|
204
|
-
// removed node's left and right subtrees
|
|
205
|
-
let removeInner = (left, right) => {
|
|
206
|
-
match ((left, right)) {
|
|
207
|
-
(Empty, node) | (node, Empty) => node,
|
|
208
|
-
(left, right) => {
|
|
209
|
-
balancedNode(min(right), left, removeMin(right))
|
|
210
|
-
},
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
/**
|
|
215
|
-
* Produces a new set without the given element. If the value doesn't exist in
|
|
216
|
-
* the set, the set will be returned unmodified.
|
|
217
|
-
*
|
|
218
|
-
* @param key: The value to exclude
|
|
219
|
-
* @param set: The set to exclude from
|
|
220
|
-
* @returns A new set without the excluded element
|
|
221
|
-
*
|
|
222
|
-
* @since v0.5.4
|
|
223
|
-
*/
|
|
224
|
-
export let rec remove = (key, set) => {
|
|
225
|
-
match (set) {
|
|
226
|
-
Empty => Empty,
|
|
227
|
-
Tree({ key: nodeKey, left, right, _ }) => {
|
|
228
|
-
match (compare(key, nodeKey)) {
|
|
229
|
-
cmp when cmp < 0 => balancedNode(nodeKey, remove(key, left), right),
|
|
230
|
-
cmp when cmp > 0 => balancedNode(nodeKey, left, remove(key, right)),
|
|
231
|
-
_ => removeInner(left, right),
|
|
232
|
-
}
|
|
233
|
-
},
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
/**
|
|
238
|
-
* Iterates the set, calling an iterator function on each element.
|
|
239
|
-
*
|
|
240
|
-
* @param fn: The iterator function to call with each element
|
|
241
|
-
* @param set: The set to iterate
|
|
242
|
-
*
|
|
243
|
-
* @since v0.5.4
|
|
244
|
-
*/
|
|
245
|
-
export let forEach = (fn, set) => {
|
|
246
|
-
let rec forEachInner = node => {
|
|
247
|
-
match (node) {
|
|
248
|
-
Empty => void,
|
|
249
|
-
Tree({ key, left, right, _ }) => {
|
|
250
|
-
forEachInner(left)
|
|
251
|
-
fn(key): Void
|
|
252
|
-
forEachInner(right)
|
|
253
|
-
},
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
forEachInner(set)
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
/**
|
|
260
|
-
* Combines all elements of a set using a reducer function.
|
|
261
|
-
*
|
|
262
|
-
* @param fn: The reducer function to call on each element, where the value returned will be the next accumulator value
|
|
263
|
-
* @param init: The initial value to use for the accumulator on the first iteration
|
|
264
|
-
* @param set: The set to iterate
|
|
265
|
-
* @returns The final accumulator returned from `fn`
|
|
266
|
-
*
|
|
267
|
-
* @since v0.5.4
|
|
268
|
-
*/
|
|
269
|
-
export let reduce = (fn, init, set) => {
|
|
270
|
-
let rec reduceInner = (acc, node) => {
|
|
271
|
-
match (node) {
|
|
272
|
-
Empty => acc,
|
|
273
|
-
Tree({ key, left, right, _ }) => {
|
|
274
|
-
let newAcc = fn(reduceInner(acc, left), key)
|
|
275
|
-
reduceInner(newAcc, right)
|
|
276
|
-
},
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
reduceInner(init, set)
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
// joins two trees with a value, preserving the BST property of left children
|
|
283
|
-
// being less the node and right children being greater than the node
|
|
284
|
-
let rec concat3 = (key, left, right) => {
|
|
285
|
-
match ((left, right)) {
|
|
286
|
-
(Empty, node) | (node, Empty) => add(key, node),
|
|
287
|
-
(Tree(left) as leftOpt, Tree(right) as rightOpt) => {
|
|
288
|
-
if (weight * left.size < right.size) {
|
|
289
|
-
balancedNode(right.key, concat3(key, leftOpt, right.left), right.right)
|
|
290
|
-
} else if (weight * right.size < left.size) {
|
|
291
|
-
balancedNode(left.key, left.left, concat3(key, left.right, rightOpt))
|
|
292
|
-
} else {
|
|
293
|
-
makeNode(key, leftOpt, rightOpt)
|
|
294
|
-
}
|
|
295
|
-
},
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
// returns a tree containing all of the nodes in the input tree whose values
|
|
300
|
-
// are less than the given value
|
|
301
|
-
let rec splitLt = (splitKey, node) => {
|
|
302
|
-
match (node) {
|
|
303
|
-
Empty => Empty,
|
|
304
|
-
Tree({ key, left, right, _ }) => {
|
|
305
|
-
match (compare(key, splitKey)) {
|
|
306
|
-
// we want this node, join it to the output
|
|
307
|
-
cmp when cmp < 0 => concat3(key, left, splitLt(splitKey, right)),
|
|
308
|
-
cmp when cmp > 0 => splitLt(splitKey, left),
|
|
309
|
-
_ => left,
|
|
310
|
-
}
|
|
311
|
-
},
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
// returns a tree containing all of the nodes in the input tree whose values
|
|
316
|
-
// are greater than the given value
|
|
317
|
-
let rec splitGt = (splitKey, node) => {
|
|
318
|
-
match (node) {
|
|
319
|
-
Empty => Empty,
|
|
320
|
-
Tree({ key, left, right, _ }) => {
|
|
321
|
-
match (compare(key, splitKey)) {
|
|
322
|
-
// we want this node, join it to the output
|
|
323
|
-
cmp when cmp > 0 => concat3(key, splitGt(splitKey, left), right),
|
|
324
|
-
cmp when cmp < 0 => splitGt(splitKey, right),
|
|
325
|
-
_ => right,
|
|
326
|
-
}
|
|
327
|
-
},
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
// concatenates two trees of arbitrary size
|
|
332
|
-
let concat = (node1, node2) => {
|
|
333
|
-
match (node2) {
|
|
334
|
-
Empty => node1,
|
|
335
|
-
_ => concat3(min(node2), node1, removeMin(node2)),
|
|
336
|
-
}
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
/**
|
|
340
|
-
* Produces a new set without the elements from the input set where a predicate function returns `false`.
|
|
341
|
-
*
|
|
342
|
-
* @param fn: The predicate function to indicate which elements to exclude from the set, where returning `false` indicates the value should be excluded
|
|
343
|
-
* @param set: The set to iterate
|
|
344
|
-
* @returns A new set excluding the elements not fulfilling the predicate
|
|
345
|
-
*
|
|
346
|
-
* @since v0.5.4
|
|
347
|
-
*/
|
|
348
|
-
export let filter = (fn, set) => {
|
|
349
|
-
let rec filterInner = node => {
|
|
350
|
-
match (node) {
|
|
351
|
-
Empty => Empty,
|
|
352
|
-
Tree({ key, left, right, _ }) => {
|
|
353
|
-
if (fn(key)) {
|
|
354
|
-
concat3(key, filterInner(left), filterInner(right))
|
|
355
|
-
} else {
|
|
356
|
-
concat(filterInner(left), filterInner(right))
|
|
357
|
-
}
|
|
358
|
-
},
|
|
359
|
-
}
|
|
360
|
-
}
|
|
361
|
-
filterInner(set)
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
/**
|
|
365
|
-
* Produces a new set without the elements from the input set where a predicate function returns `true`.
|
|
366
|
-
*
|
|
367
|
-
* @param fn: The predicate function to indicate which elements to exclude from the set, where returning `true` indicates the value should be excluded
|
|
368
|
-
* @param set: The set to iterate
|
|
369
|
-
* @returns A new set excluding the elements fulfilling the predicate
|
|
370
|
-
*
|
|
371
|
-
* @since v0.5.4
|
|
372
|
-
*/
|
|
373
|
-
export let reject = (fn, set) => {
|
|
374
|
-
filter(key => !fn(key), set)
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
/**
|
|
378
|
-
* Combines two sets into a single set containing all elements from both sets.
|
|
379
|
-
*
|
|
380
|
-
* @param set1: The first set to combine
|
|
381
|
-
* @param set2: The second set to combine
|
|
382
|
-
* @returns A set containing all elements of both sets
|
|
383
|
-
*
|
|
384
|
-
* @since v0.5.4
|
|
385
|
-
*/
|
|
386
|
-
export let rec union = (set1, set2) => {
|
|
387
|
-
match ((set1, set2)) {
|
|
388
|
-
(Empty, node) | (node, Empty) => node,
|
|
389
|
-
(node1, Tree(node2)) => {
|
|
390
|
-
let l = splitLt(node2.key, node1)
|
|
391
|
-
let r = splitGt(node2.key, node1)
|
|
392
|
-
concat3(node2.key, union(l, node2.left), union(r, node2.right))
|
|
393
|
-
},
|
|
394
|
-
}
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
/**
|
|
398
|
-
* Combines two sets into a single set containing only the elements not shared between both sets.
|
|
399
|
-
*
|
|
400
|
-
* @param set1: The first set to combine
|
|
401
|
-
* @param set2: The second set to combine
|
|
402
|
-
* @returns A set containing only unshared elements from both sets
|
|
403
|
-
*
|
|
404
|
-
* @since v0.5.4
|
|
405
|
-
*/
|
|
406
|
-
export let diff = (set1, set2) => {
|
|
407
|
-
let rec diffInner = (node1, node2) => {
|
|
408
|
-
match ((node1, node2)) {
|
|
409
|
-
(Empty, node) | (node, Empty) => node,
|
|
410
|
-
(node1, Tree(node2)) => {
|
|
411
|
-
let l = splitLt(node2.key, node1)
|
|
412
|
-
let r = splitGt(node2.key, node1)
|
|
413
|
-
concat(diffInner(l, node2.left), diffInner(r, node2.right))
|
|
414
|
-
},
|
|
415
|
-
}
|
|
416
|
-
}
|
|
417
|
-
union(diffInner(set1, set2), diffInner(set2, set1))
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
/**
|
|
421
|
-
* Combines two sets into a single set containing only the elements shared between both sets.
|
|
422
|
-
*
|
|
423
|
-
* @param set1: The first set to combine
|
|
424
|
-
* @param set2: The second set to combine
|
|
425
|
-
* @returns A set containing only shared elements from both sets
|
|
426
|
-
*
|
|
427
|
-
* @since v0.5.4
|
|
428
|
-
*/
|
|
429
|
-
export let rec intersect = (set1, set2) => {
|
|
430
|
-
match ((set1, set2)) {
|
|
431
|
-
(Empty, _) | (_, Empty) => Empty,
|
|
432
|
-
(node1, Tree(node2)) => {
|
|
433
|
-
let l = splitLt(node2.key, node1)
|
|
434
|
-
let r = splitGt(node2.key, node1)
|
|
435
|
-
if (contains(node2.key, node1)) {
|
|
436
|
-
concat3(node2.key, intersect(l, node2.left), intersect(r, node2.right))
|
|
437
|
-
} else {
|
|
438
|
-
concat(intersect(l, node2.left), intersect(r, node2.right))
|
|
439
|
-
}
|
|
440
|
-
},
|
|
441
|
-
}
|
|
442
|
-
}
|
|
443
|
-
|
|
444
|
-
/**
|
|
445
|
-
* Creates a set from a list.
|
|
446
|
-
*
|
|
447
|
-
* @param list: The list to convert
|
|
448
|
-
* @returns A set containing all list values
|
|
449
|
-
*
|
|
450
|
-
* @since v0.5.4
|
|
451
|
-
*/
|
|
452
|
-
export let fromList = list => {
|
|
453
|
-
List.reduce((set, key) => add(key, set), empty, list)
|
|
454
|
-
}
|
|
455
|
-
|
|
456
|
-
/**
|
|
457
|
-
* Converts a set into a list of its elements.
|
|
458
|
-
*
|
|
459
|
-
* @param set: The set to convert
|
|
460
|
-
* @returns A list containing all set values
|
|
461
|
-
*
|
|
462
|
-
* @since v0.5.4
|
|
463
|
-
*/
|
|
464
|
-
export let toList = set => {
|
|
465
|
-
let rec toListInner = (acc, node) => {
|
|
466
|
-
match (node) {
|
|
467
|
-
Empty => acc,
|
|
468
|
-
Tree({ key, left, right, _ }) => {
|
|
469
|
-
toListInner([key, ...toListInner(acc, right)], left)
|
|
470
|
-
},
|
|
471
|
-
}
|
|
472
|
-
}
|
|
473
|
-
toListInner([], set)
|
|
474
|
-
}
|
|
475
|
-
|
|
476
|
-
/**
|
|
477
|
-
* Creates a set from an array.
|
|
478
|
-
*
|
|
479
|
-
* @param array: The array to convert
|
|
480
|
-
* @returns A set containing all array values
|
|
481
|
-
*
|
|
482
|
-
* @since v0.5.4
|
|
483
|
-
*/
|
|
484
|
-
export let fromArray = array => {
|
|
485
|
-
Array.reduce((set, key) => add(key, set), empty, array)
|
|
486
|
-
}
|
|
487
|
-
|
|
488
|
-
/**
|
|
489
|
-
* Converts a set into an array of its elements.
|
|
490
|
-
*
|
|
491
|
-
* @param set: The set to convert
|
|
492
|
-
* @returns An array containing all set values
|
|
493
|
-
*
|
|
494
|
-
* @since v0.5.4
|
|
495
|
-
*/
|
|
496
|
-
export let toArray = set => {
|
|
497
|
-
Array.fromList(toList(set))
|
|
498
|
-
}
|