@grain/stdlib 0.4.2 → 0.4.6
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 +52 -0
- package/LICENSE +1 -1
- package/array.gr +200 -89
- package/array.md +81 -5
- package/buffer.gr +93 -36
- package/bytes.gr +10 -10
- package/char.gr +112 -56
- package/char.md +200 -0
- package/float32.gr +120 -4
- package/float32.md +315 -0
- package/float64.gr +120 -4
- package/float64.md +315 -0
- package/hash.gr +42 -15
- package/hash.md +44 -0
- package/int32.gr +370 -75
- package/int32.md +833 -0
- package/int64.gr +370 -75
- package/int64.md +833 -0
- package/list.gr +121 -50
- package/map.gr +106 -110
- package/number.gr +37 -1
- package/number.md +66 -0
- package/option.gr +260 -53
- package/option.md +579 -0
- package/package.json +1 -1
- package/pervasives.gr +32 -20
- package/queue.gr +102 -30
- package/queue.md +191 -0
- package/range.gr +26 -26
- package/range.md +1 -1
- package/regex.md +9 -9
- package/result.gr +216 -70
- package/result.md +446 -0
- package/runtime/dataStructures.gr +28 -29
- package/runtime/debug.gr +0 -1
- package/runtime/equal.gr +37 -16
- package/runtime/exception.gr +28 -15
- package/runtime/gc.gr +33 -20
- package/runtime/malloc.gr +19 -11
- package/runtime/numberUtils.gr +208 -103
- package/runtime/numbers.gr +217 -118
- package/runtime/string.gr +98 -39
- package/runtime/stringUtils.gr +176 -0
- package/runtime/unsafe/conv.gr +10 -10
- package/runtime/unsafe/memory.gr +14 -3
- package/runtime/unsafe/printWasm.gr +4 -4
- package/runtime/unsafe/tags.gr +2 -2
- package/runtime/unsafe/wasmf32.gr +9 -2
- package/runtime/unsafe/wasmf64.gr +9 -2
- package/runtime/unsafe/wasmi32.gr +65 -47
- package/runtime/unsafe/wasmi64.gr +78 -50
- package/runtime/wasi.gr +199 -45
- package/set.gr +281 -119
- package/set.md +502 -0
- package/stack.gr +26 -26
- package/string.gr +657 -341
- package/string.md +815 -0
- package/sys/file.gr +356 -177
- package/sys/process.gr +10 -6
- package/sys/random.gr +3 -6
- package/sys/time.gr +3 -3
package/set.gr
CHANGED
|
@@ -1,35 +1,50 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
/**
|
|
2
|
+
* @module Set: A Set is an unordered collection of unique values. Operations on a Set mutate the internal state, so it never needs to be re-assigned.
|
|
3
|
+
* @example import Set from "set"
|
|
4
|
+
*
|
|
5
|
+
* @since 0.3.0
|
|
6
|
+
*/
|
|
3
7
|
import List from "list"
|
|
4
8
|
import Array from "array"
|
|
5
9
|
import { hash } from "hash"
|
|
6
10
|
|
|
7
11
|
record Bucket<t> {
|
|
8
12
|
mut key: t,
|
|
9
|
-
mut next: Option<Bucket<t
|
|
13
|
+
mut next: Option<Bucket<t>>,
|
|
10
14
|
}
|
|
11
15
|
|
|
12
16
|
record Set<k> {
|
|
13
17
|
mut size: Number,
|
|
14
|
-
mut buckets: Array<Option<Bucket<k
|
|
18
|
+
mut buckets: Array<Option<Bucket<k>>>,
|
|
15
19
|
}
|
|
16
20
|
|
|
17
21
|
// TODO: This could take an `eq` function to custom comparisons
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
/**
|
|
23
|
+
* Creates a new empty set with an initial storage of the given length. As values are added or removed, the length may grow or shrink. Generally, you won't need to care about the length of your set and can use `Set.make()` instead.
|
|
24
|
+
*
|
|
25
|
+
* @param storageLength: The initial storage length of the set
|
|
26
|
+
* @returns An empty set with the given initial storage length
|
|
27
|
+
*
|
|
28
|
+
* @since 0.3.0
|
|
29
|
+
*/
|
|
30
|
+
export let makeSized = storageLength => {
|
|
31
|
+
let buckets = Array.make(storageLength, None)
|
|
32
|
+
{ size: 0, buckets }
|
|
24
33
|
}
|
|
25
|
-
|
|
34
|
+
/**
|
|
35
|
+
* Creates a new, empty set.
|
|
36
|
+
*
|
|
37
|
+
* @returns An empty set
|
|
38
|
+
*
|
|
39
|
+
* @since 0.3.0
|
|
40
|
+
*/
|
|
26
41
|
export let make = () => {
|
|
27
42
|
makeSized(16)
|
|
28
43
|
}
|
|
29
44
|
|
|
30
45
|
let getBucketIndex = (key, buckets) => {
|
|
31
|
-
let bucketsLength = Array.length(buckets)
|
|
32
|
-
let hashedKey = hash(key)
|
|
46
|
+
let bucketsLength = Array.length(buckets)
|
|
47
|
+
let hashedKey = hash(key)
|
|
33
48
|
hashedKey % bucketsLength
|
|
34
49
|
}
|
|
35
50
|
|
|
@@ -37,45 +52,45 @@ let rec copyNodeWithNewHash = (oldNode, next, tail) => {
|
|
|
37
52
|
match (oldNode) {
|
|
38
53
|
None => void,
|
|
39
54
|
Some(node) => {
|
|
40
|
-
let idx = getBucketIndex(node.key, next)
|
|
41
|
-
let newNode = Some(node)
|
|
55
|
+
let idx = getBucketIndex(node.key, next)
|
|
56
|
+
let newNode = Some(node)
|
|
42
57
|
match (tail[idx]) {
|
|
43
58
|
None => {
|
|
44
|
-
next[idx] = newNode
|
|
59
|
+
next[idx] = newNode
|
|
45
60
|
},
|
|
46
61
|
Some(tailNode) => {
|
|
47
62
|
// If there's already a tail node, we add this to the end
|
|
48
|
-
tailNode.next = newNode
|
|
49
|
-
}
|
|
63
|
+
tailNode.next = newNode
|
|
64
|
+
},
|
|
50
65
|
}
|
|
51
66
|
// Always place this node as the new tail
|
|
52
|
-
tail[idx] = newNode
|
|
67
|
+
tail[idx] = newNode
|
|
53
68
|
// Recurse with the next node
|
|
54
|
-
copyNodeWithNewHash(node.next, next, tail)
|
|
55
|
-
}
|
|
69
|
+
copyNodeWithNewHash(node.next, next, tail)
|
|
70
|
+
},
|
|
56
71
|
}
|
|
57
72
|
}
|
|
58
73
|
|
|
59
|
-
let resize =
|
|
60
|
-
let currentBuckets = set.buckets
|
|
61
|
-
let currentSize = Array.length(currentBuckets)
|
|
62
|
-
let nextSize = currentSize * 2
|
|
74
|
+
let resize = set => {
|
|
75
|
+
let currentBuckets = set.buckets
|
|
76
|
+
let currentSize = Array.length(currentBuckets)
|
|
77
|
+
let nextSize = currentSize * 2
|
|
63
78
|
if (nextSize >= currentSize) {
|
|
64
|
-
let nextBuckets = Array.make(nextSize, None)
|
|
79
|
+
let nextBuckets = Array.make(nextSize, None)
|
|
65
80
|
// This tracks the tail nodes so we can set their `next` to None
|
|
66
|
-
let tailNodes = Array.make(nextSize, None)
|
|
67
|
-
set.buckets = nextBuckets
|
|
68
|
-
Array.forEach(
|
|
69
|
-
copyNodeWithNewHash(old, nextBuckets, tailNodes)
|
|
70
|
-
}, currentBuckets)
|
|
71
|
-
Array.forEach(
|
|
81
|
+
let tailNodes = Array.make(nextSize, None)
|
|
82
|
+
set.buckets = nextBuckets
|
|
83
|
+
Array.forEach(old => {
|
|
84
|
+
copyNodeWithNewHash(old, nextBuckets, tailNodes)
|
|
85
|
+
}, currentBuckets)
|
|
86
|
+
Array.forEach(tail => {
|
|
72
87
|
match (tail) {
|
|
73
88
|
None => void,
|
|
74
89
|
Some(node) => {
|
|
75
|
-
node.next = None
|
|
76
|
-
}
|
|
90
|
+
node.next = None
|
|
91
|
+
},
|
|
77
92
|
}
|
|
78
|
-
}, tailNodes)
|
|
93
|
+
}, tailNodes)
|
|
79
94
|
} else {
|
|
80
95
|
void
|
|
81
96
|
}
|
|
@@ -87,42 +102,59 @@ let rec nodeInBucket = (key, node) => {
|
|
|
87
102
|
} else {
|
|
88
103
|
match (node.next) {
|
|
89
104
|
None => false,
|
|
90
|
-
Some(next) => nodeInBucket(key, next)
|
|
105
|
+
Some(next) => nodeInBucket(key, next),
|
|
91
106
|
}
|
|
92
107
|
}
|
|
93
108
|
}
|
|
94
109
|
|
|
110
|
+
/**
|
|
111
|
+
* Adds a new value to the set. If the value already exists, nothing happens.
|
|
112
|
+
*
|
|
113
|
+
* @param key: The value to add
|
|
114
|
+
* @param set: The set to update
|
|
115
|
+
*
|
|
116
|
+
* @since 0.3.0
|
|
117
|
+
*/
|
|
95
118
|
export let add = (key, set) => {
|
|
96
|
-
let buckets = set.buckets
|
|
119
|
+
let buckets = set.buckets
|
|
97
120
|
let idx = getBucketIndex(key, buckets)
|
|
98
|
-
let bucket = buckets[idx]
|
|
121
|
+
let bucket = buckets[idx]
|
|
99
122
|
match (bucket) {
|
|
100
123
|
None => {
|
|
101
|
-
buckets[idx] = Some({ key, next: None })
|
|
102
|
-
set.size = incr(set.size)
|
|
124
|
+
buckets[idx] = Some({ key, next: None })
|
|
125
|
+
set.size = incr(set.size)
|
|
103
126
|
},
|
|
104
127
|
Some(node) => {
|
|
105
128
|
if (!nodeInBucket(key, node)) {
|
|
106
|
-
buckets[idx] = Some({ key, next: bucket })
|
|
107
|
-
set.size = incr(set.size)
|
|
108
|
-
}
|
|
109
|
-
}
|
|
129
|
+
buckets[idx] = Some({ key, next: bucket })
|
|
130
|
+
set.size = incr(set.size)
|
|
131
|
+
}
|
|
132
|
+
},
|
|
110
133
|
}
|
|
111
134
|
// Resize if there are more than 2x the amount of nodes as buckets
|
|
112
|
-
if (set.size >
|
|
113
|
-
resize(set)
|
|
135
|
+
if (set.size > Array.length(buckets) * 2) {
|
|
136
|
+
resize(set)
|
|
114
137
|
} else {
|
|
115
138
|
void
|
|
116
139
|
}
|
|
117
140
|
}
|
|
118
141
|
|
|
142
|
+
/**
|
|
143
|
+
* Determines if the set contains the given value.
|
|
144
|
+
*
|
|
145
|
+
* @param key: The value to search for
|
|
146
|
+
* @param set: The set to search
|
|
147
|
+
* @returns `true` if the set contains the given value or `false` otherwise
|
|
148
|
+
*
|
|
149
|
+
* @since 0.3.0
|
|
150
|
+
*/
|
|
119
151
|
export let contains = (key, set) => {
|
|
120
|
-
let buckets = set.buckets
|
|
121
|
-
let idx = getBucketIndex(key, buckets)
|
|
122
|
-
let bucket = buckets[idx]
|
|
152
|
+
let buckets = set.buckets
|
|
153
|
+
let idx = getBucketIndex(key, buckets)
|
|
154
|
+
let bucket = buckets[idx]
|
|
123
155
|
match (bucket) {
|
|
124
156
|
None => false,
|
|
125
|
-
Some(node) => nodeInBucket(key, node)
|
|
157
|
+
Some(node) => nodeInBucket(key, node),
|
|
126
158
|
}
|
|
127
159
|
}
|
|
128
160
|
|
|
@@ -131,168 +163,298 @@ let rec removeInBucket = (key, node) => {
|
|
|
131
163
|
None => false,
|
|
132
164
|
Some(next) => {
|
|
133
165
|
if (key == next.key) {
|
|
134
|
-
node.next = next.next
|
|
166
|
+
node.next = next.next
|
|
135
167
|
true
|
|
136
168
|
} else {
|
|
137
169
|
removeInBucket(key, next)
|
|
138
170
|
}
|
|
139
|
-
}
|
|
171
|
+
},
|
|
140
172
|
}
|
|
141
173
|
}
|
|
142
174
|
|
|
175
|
+
/**
|
|
176
|
+
* Removes the given value from the set. If the value doesn't exist, nothing happens.
|
|
177
|
+
*
|
|
178
|
+
* @param key: The value to remove
|
|
179
|
+
* @param set: The set to update
|
|
180
|
+
*
|
|
181
|
+
* @since 0.3.0
|
|
182
|
+
*/
|
|
143
183
|
export let remove = (key, set) => {
|
|
144
|
-
let buckets = set.buckets
|
|
145
|
-
let idx = getBucketIndex(key, buckets)
|
|
146
|
-
let bucket = buckets[idx]
|
|
184
|
+
let buckets = set.buckets
|
|
185
|
+
let idx = getBucketIndex(key, buckets)
|
|
186
|
+
let bucket = buckets[idx]
|
|
147
187
|
match (bucket) {
|
|
148
188
|
None => void,
|
|
149
189
|
Some(node) => {
|
|
150
190
|
// If it is a top-level node, just replace with next node
|
|
151
191
|
if (key == node.key) {
|
|
152
|
-
set.size = decr(set.size)
|
|
153
|
-
buckets[idx] = node.next
|
|
192
|
+
set.size = decr(set.size)
|
|
193
|
+
buckets[idx] = node.next
|
|
154
194
|
} else {
|
|
155
195
|
if (removeInBucket(key, node)) {
|
|
156
|
-
set.size = decr(set.size)
|
|
196
|
+
set.size = decr(set.size)
|
|
157
197
|
}
|
|
158
198
|
}
|
|
159
|
-
}
|
|
199
|
+
},
|
|
160
200
|
}
|
|
161
201
|
}
|
|
162
202
|
|
|
163
|
-
|
|
203
|
+
/**
|
|
204
|
+
* Returns the number of values within the set.
|
|
205
|
+
*
|
|
206
|
+
* @param set: The set to inspect
|
|
207
|
+
* @returns The number of elements in the set
|
|
208
|
+
*
|
|
209
|
+
* @since 0.3.0
|
|
210
|
+
*/
|
|
211
|
+
export let size = set => {
|
|
164
212
|
set.size
|
|
165
213
|
}
|
|
166
214
|
|
|
167
|
-
|
|
215
|
+
/**
|
|
216
|
+
* Determines if the set contains no elements.
|
|
217
|
+
*
|
|
218
|
+
* @param set: The set to inspect
|
|
219
|
+
* @returns `true` if the given set is empty or `false` otherwise
|
|
220
|
+
*
|
|
221
|
+
* @since 0.3.0
|
|
222
|
+
*/
|
|
223
|
+
export let isEmpty = set => {
|
|
168
224
|
size(set) == 0
|
|
169
225
|
}
|
|
170
226
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
227
|
+
/**
|
|
228
|
+
* Resets the set by removing all values.
|
|
229
|
+
*
|
|
230
|
+
* @param set: The set to reset
|
|
231
|
+
*
|
|
232
|
+
* @since 0.3.0
|
|
233
|
+
*/
|
|
234
|
+
export let clear = set => {
|
|
235
|
+
set.size = 0
|
|
236
|
+
let buckets = set.buckets
|
|
174
237
|
Array.forEachi((bucket, idx) => {
|
|
175
|
-
buckets[idx] = None
|
|
176
|
-
}, buckets)
|
|
238
|
+
buckets[idx] = None
|
|
239
|
+
}, buckets)
|
|
177
240
|
}
|
|
178
241
|
|
|
179
242
|
let rec forEachBucket = (fn, node) => {
|
|
180
243
|
match (node) {
|
|
181
244
|
None => void,
|
|
182
245
|
Some({ key, next }) => {
|
|
183
|
-
fn(key)
|
|
184
|
-
forEachBucket(fn, next)
|
|
185
|
-
}
|
|
246
|
+
fn(key)
|
|
247
|
+
forEachBucket(fn, next)
|
|
248
|
+
},
|
|
186
249
|
}
|
|
187
250
|
}
|
|
188
251
|
|
|
252
|
+
/**
|
|
253
|
+
* Iterates the set, calling an iterator function on each element.
|
|
254
|
+
*
|
|
255
|
+
* @param fn: The iterator function to call with each element
|
|
256
|
+
* @param set: The set to iterate
|
|
257
|
+
*
|
|
258
|
+
* @since 0.3.0
|
|
259
|
+
*/
|
|
189
260
|
export let forEach = (fn, set) => {
|
|
190
|
-
let buckets = set.buckets
|
|
191
|
-
Array.forEach(
|
|
261
|
+
let buckets = set.buckets
|
|
262
|
+
Array.forEach(bucket => {
|
|
192
263
|
forEachBucket(fn, bucket)
|
|
193
|
-
}, buckets)
|
|
264
|
+
}, buckets)
|
|
194
265
|
}
|
|
195
266
|
|
|
196
267
|
let rec reduceEachBucket = (fn, node, acc) => {
|
|
197
268
|
match (node) {
|
|
198
269
|
None => acc,
|
|
199
|
-
Some({ key, next }) =>
|
|
200
|
-
reduceEachBucket(fn, next, fn(acc, key))
|
|
270
|
+
Some({ key, next }) => reduceEachBucket(fn, next, fn(acc, key)),
|
|
201
271
|
}
|
|
202
272
|
}
|
|
203
273
|
|
|
274
|
+
/**
|
|
275
|
+
* Combines all elements of a set using a reducer function.
|
|
276
|
+
*
|
|
277
|
+
* @param fn: The reducer function to call on each element, where the value returned will be the next accumulator value
|
|
278
|
+
* @param init: The initial value to use for the accumulator on the first iteration
|
|
279
|
+
* @param set: The set to iterate
|
|
280
|
+
* @returns The final accumulator returned from `fn`
|
|
281
|
+
*
|
|
282
|
+
* @since 0.3.0
|
|
283
|
+
*/
|
|
204
284
|
export let reduce = (fn, init, set) => {
|
|
205
|
-
let buckets = set.buckets
|
|
206
|
-
let mut acc = init
|
|
207
|
-
Array.forEach(
|
|
285
|
+
let buckets = set.buckets
|
|
286
|
+
let mut acc = init
|
|
287
|
+
Array.forEach(bucket => {
|
|
208
288
|
acc = reduceEachBucket(fn, bucket, acc)
|
|
209
|
-
}, buckets)
|
|
289
|
+
}, buckets)
|
|
210
290
|
acc
|
|
211
291
|
}
|
|
212
292
|
|
|
293
|
+
/**
|
|
294
|
+
* Removes elements from a set where a predicate function returns `false`.
|
|
295
|
+
*
|
|
296
|
+
* @param fn: The predicate function to indicate which elements to remove from the set, where returning `false` indicates the value should be removed
|
|
297
|
+
* @param set: The set to iterate
|
|
298
|
+
*
|
|
299
|
+
* @since 0.3.0
|
|
300
|
+
*/
|
|
213
301
|
export let filter = (predicate, set) => {
|
|
214
|
-
let keysToRemove = reduce((list, key) =>
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
}, keysToRemove);
|
|
302
|
+
let keysToRemove = reduce((list, key) => if (!predicate(key)) {
|
|
303
|
+
[key, ...list]
|
|
304
|
+
} else {
|
|
305
|
+
list
|
|
306
|
+
}, [], set)
|
|
307
|
+
List.forEach(key => {
|
|
308
|
+
remove(key, set)
|
|
309
|
+
}, keysToRemove)
|
|
223
310
|
}
|
|
224
311
|
|
|
312
|
+
/**
|
|
313
|
+
* Removes elements from a set where a predicate function returns `true`.
|
|
314
|
+
*
|
|
315
|
+
* @param fn: The predicate function to indicate which elements to remove from the set, where returning `true` indicates the value should be removed
|
|
316
|
+
* @param set: The set to iterate
|
|
317
|
+
*
|
|
318
|
+
* @since 0.3.0
|
|
319
|
+
*/
|
|
225
320
|
export let reject = (predicate, set) => {
|
|
226
|
-
filter(
|
|
321
|
+
filter(key => !predicate(key), set)
|
|
227
322
|
}
|
|
228
323
|
|
|
229
|
-
|
|
324
|
+
/**
|
|
325
|
+
* Converts a set into a list of its elements.
|
|
326
|
+
*
|
|
327
|
+
* @param set: The set to convert
|
|
328
|
+
* @returns A list containing all set values
|
|
329
|
+
*
|
|
330
|
+
* @since 0.3.0
|
|
331
|
+
*/
|
|
332
|
+
export let toList = set => {
|
|
230
333
|
reduce((list, key) => [key, ...list], [], set)
|
|
231
334
|
}
|
|
232
335
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
336
|
+
/**
|
|
337
|
+
* Creates a set from a list.
|
|
338
|
+
*
|
|
339
|
+
* @param list: The list to convert
|
|
340
|
+
* @returns A set containing all list values
|
|
341
|
+
*
|
|
342
|
+
* @since 0.3.0
|
|
343
|
+
*/
|
|
344
|
+
export let fromList = list => {
|
|
345
|
+
let set = make()
|
|
346
|
+
List.forEach(key => {
|
|
347
|
+
add(key, set)
|
|
348
|
+
}, list)
|
|
238
349
|
set
|
|
239
350
|
}
|
|
240
351
|
|
|
241
|
-
|
|
352
|
+
/**
|
|
353
|
+
* Converts a set into an array of its elements.
|
|
354
|
+
*
|
|
355
|
+
* @param set: The set to convert
|
|
356
|
+
* @returns An array containing all set values
|
|
357
|
+
*
|
|
358
|
+
* @since 0.3.0
|
|
359
|
+
*/
|
|
360
|
+
export let toArray = set => {
|
|
242
361
|
Array.fromList(toList(set))
|
|
243
362
|
}
|
|
244
363
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
364
|
+
/**
|
|
365
|
+
* Creates a set from an array.
|
|
366
|
+
*
|
|
367
|
+
* @param array: The array to convert
|
|
368
|
+
* @returns A set containing all array values
|
|
369
|
+
*
|
|
370
|
+
* @since 0.3.0
|
|
371
|
+
*/
|
|
372
|
+
export let fromArray = array => {
|
|
373
|
+
let set = make()
|
|
374
|
+
Array.forEach(key => {
|
|
375
|
+
add(key, set)
|
|
376
|
+
}, array)
|
|
250
377
|
set
|
|
251
378
|
}
|
|
252
379
|
|
|
380
|
+
/**
|
|
381
|
+
* Combines two sets into a single set containing all elements from both sets.
|
|
382
|
+
*
|
|
383
|
+
* @param set1: The first set to combine
|
|
384
|
+
* @param set2: The second set to combine
|
|
385
|
+
* @returns A set containing all elements of both sets
|
|
386
|
+
*
|
|
387
|
+
* @since 0.3.0
|
|
388
|
+
*/
|
|
253
389
|
export let union = (set1, set2) => {
|
|
254
|
-
let set = make()
|
|
255
|
-
forEach(
|
|
256
|
-
add(key, set)
|
|
390
|
+
let set = make()
|
|
391
|
+
forEach(key => {
|
|
392
|
+
add(key, set)
|
|
257
393
|
}, set1)
|
|
258
|
-
forEach(
|
|
259
|
-
add(key, set)
|
|
260
|
-
}, set2)
|
|
394
|
+
forEach(key => {
|
|
395
|
+
add(key, set)
|
|
396
|
+
}, set2)
|
|
261
397
|
set
|
|
262
398
|
}
|
|
263
399
|
|
|
400
|
+
/**
|
|
401
|
+
* Combines two sets into a single set containing only the elements not shared between both sets.
|
|
402
|
+
*
|
|
403
|
+
* @param set1: The first set to combine
|
|
404
|
+
* @param set2: The second set to combine
|
|
405
|
+
* @returns A set containing only unshared elements from both sets
|
|
406
|
+
*
|
|
407
|
+
* @since 0.3.0
|
|
408
|
+
*/
|
|
264
409
|
export let diff = (set1, set2) => {
|
|
265
|
-
let set = make()
|
|
266
|
-
forEach(
|
|
410
|
+
let set = make()
|
|
411
|
+
forEach(key => {
|
|
267
412
|
if (!contains(key, set2)) {
|
|
268
|
-
add(key, set)
|
|
413
|
+
add(key, set)
|
|
269
414
|
}
|
|
270
415
|
}, set1)
|
|
271
|
-
forEach(
|
|
416
|
+
forEach(key => {
|
|
272
417
|
if (!contains(key, set1)) {
|
|
273
|
-
add(key, set)
|
|
418
|
+
add(key, set)
|
|
274
419
|
}
|
|
275
|
-
}, set2)
|
|
420
|
+
}, set2)
|
|
276
421
|
set
|
|
277
422
|
}
|
|
278
423
|
|
|
424
|
+
/**
|
|
425
|
+
* Combines two sets into a single set containing only the elements shared between both sets.
|
|
426
|
+
*
|
|
427
|
+
* @param set1: The first set to combine
|
|
428
|
+
* @param set2: The second set to combine
|
|
429
|
+
* @returns A set containing only shared elements from both sets
|
|
430
|
+
*
|
|
431
|
+
* @since 0.3.0
|
|
432
|
+
*/
|
|
279
433
|
export let intersect = (set1, set2) => {
|
|
280
|
-
let set = make()
|
|
281
|
-
forEach(
|
|
434
|
+
let set = make()
|
|
435
|
+
forEach(key => {
|
|
282
436
|
if (contains(key, set2)) {
|
|
283
|
-
add(key, set)
|
|
437
|
+
add(key, set)
|
|
284
438
|
}
|
|
285
439
|
}, set1)
|
|
286
|
-
forEach(
|
|
440
|
+
forEach(key => {
|
|
287
441
|
if (contains(key, set1)) {
|
|
288
|
-
add(key, set)
|
|
442
|
+
add(key, set)
|
|
289
443
|
}
|
|
290
|
-
}, set2)
|
|
444
|
+
}, set2)
|
|
291
445
|
set
|
|
292
446
|
}
|
|
293
447
|
|
|
294
448
|
// TODO: Should return a Record type instead of a Tuple
|
|
295
449
|
// Waiting on https://github.com/grain-lang/grain/issues/190
|
|
296
|
-
|
|
450
|
+
/**
|
|
451
|
+
* Provides data representing the internal state state of the set.
|
|
452
|
+
*
|
|
453
|
+
* @param set: The set to inspect
|
|
454
|
+
* @returns The internal state of the set
|
|
455
|
+
*
|
|
456
|
+
* @since 0.3.0
|
|
457
|
+
*/
|
|
458
|
+
export let getInternalStats = set => {
|
|
297
459
|
(set.size, Array.length(set.buckets))
|
|
298
460
|
}
|