@grain/stdlib 0.5.2 → 0.5.3
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 +21 -0
- package/array.gr +56 -1
- package/array.md +83 -0
- package/bigint.md +30 -30
- package/buffer.gr +24 -22
- package/float32.md +3 -3
- package/float64.md +3 -3
- package/immutablepriorityqueue.gr +332 -0
- package/immutablepriorityqueue.md +248 -0
- package/list.gr +73 -0
- package/list.md +110 -0
- package/map.gr +1 -2
- package/marshal.gr +1058 -0
- package/marshal.md +76 -0
- package/number.gr +41 -0
- package/number.md +80 -5
- package/package.json +1 -1
- package/pervasives.gr +16 -5
- package/pervasives.md +28 -0
- package/priorityqueue.gr +241 -0
- package/priorityqueue.md +279 -0
- package/regex.gr +5 -5
- package/runtime/compare.gr +178 -0
- package/runtime/compare.md +6 -0
- package/runtime/equal.gr +1 -2
- package/runtime/numbers.gr +307 -68
- package/runtime/numbers.md +24 -0
- package/set.gr +1 -2
- package/string.gr +97 -15
- package/string.md +65 -1
- package/sys/file.gr +3 -3
- package/sys/file.md +3 -3
- package/sys/process.gr +3 -3
- package/sys/process.md +3 -3
- package/sys/random.gr +2 -2
- package/sys/random.md +2 -2
- package/sys/time.gr +2 -2
- package/sys/time.md +2 -2
package/marshal.md
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Marshal
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Utilities for serializing and deserializing Grain data.
|
|
6
|
+
|
|
7
|
+
<details disabled>
|
|
8
|
+
<summary tabindex="-1">Added in <code>0.5.3</code></summary>
|
|
9
|
+
No other changes yet.
|
|
10
|
+
</details>
|
|
11
|
+
|
|
12
|
+
```grain
|
|
13
|
+
import Marshal from "marshal"
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Values
|
|
17
|
+
|
|
18
|
+
Functions for marshaling and unmarshaling data.
|
|
19
|
+
|
|
20
|
+
### Marshal.**marshal**
|
|
21
|
+
|
|
22
|
+
<details disabled>
|
|
23
|
+
<summary tabindex="-1">Added in <code>0.5.3</code></summary>
|
|
24
|
+
No other changes yet.
|
|
25
|
+
</details>
|
|
26
|
+
|
|
27
|
+
```grain
|
|
28
|
+
marshal : a -> Bytes
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Serialize a value into a byte-based representation suitable for transmission
|
|
32
|
+
across a network or disk storage. The byte-based representation can be
|
|
33
|
+
deserialized at a later time to restore the value.
|
|
34
|
+
|
|
35
|
+
Parameters:
|
|
36
|
+
|
|
37
|
+
|param|type|description|
|
|
38
|
+
|-----|----|-----------|
|
|
39
|
+
|`value`|`a`|The value to serialize|
|
|
40
|
+
|
|
41
|
+
Returns:
|
|
42
|
+
|
|
43
|
+
|type|description|
|
|
44
|
+
|----|-----------|
|
|
45
|
+
|`Bytes`|A byte-based representation of the value|
|
|
46
|
+
|
|
47
|
+
### Marshal.**unmarshal**
|
|
48
|
+
|
|
49
|
+
<details disabled>
|
|
50
|
+
<summary tabindex="-1">Added in <code>0.5.3</code></summary>
|
|
51
|
+
No other changes yet.
|
|
52
|
+
</details>
|
|
53
|
+
|
|
54
|
+
```grain
|
|
55
|
+
unmarshal : Bytes -> Result<a, String>
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Deserialize the byte-based representation of a value back into an in-memory
|
|
59
|
+
value. This operation is not type-safe, and it is recommended that a type
|
|
60
|
+
annotation is used to declare the type of the unmarshaled value. While
|
|
61
|
+
attempts to unmarshal bad data will fail, this operation is still generally
|
|
62
|
+
unsafe and great care should be taken to ensure that the data being
|
|
63
|
+
unmarshaled corresponds to the expected type.
|
|
64
|
+
|
|
65
|
+
Parameters:
|
|
66
|
+
|
|
67
|
+
|param|type|description|
|
|
68
|
+
|-----|----|-----------|
|
|
69
|
+
|`bytes`|`Bytes`|The data to deserialize|
|
|
70
|
+
|
|
71
|
+
Returns:
|
|
72
|
+
|
|
73
|
+
|type|description|
|
|
74
|
+
|----|-----------|
|
|
75
|
+
|`Result<a, String>`|An in-memory value|
|
|
76
|
+
|
package/number.gr
CHANGED
|
@@ -13,6 +13,8 @@ import {
|
|
|
13
13
|
coerceNumberToWasmF64,
|
|
14
14
|
reducedInteger,
|
|
15
15
|
isFloat,
|
|
16
|
+
isInteger,
|
|
17
|
+
isRational,
|
|
16
18
|
isBoxedNumber,
|
|
17
19
|
} from "runtime/numbers"
|
|
18
20
|
import { parseInt } from "runtime/stringUtils"
|
|
@@ -232,6 +234,45 @@ export let abs = (x: Number) => if (0 > x) x * -1 else x
|
|
|
232
234
|
*/
|
|
233
235
|
export let neg = (x: Number) => x * -1
|
|
234
236
|
|
|
237
|
+
/**
|
|
238
|
+
* Checks if a number is a floating point value.
|
|
239
|
+
*
|
|
240
|
+
* @param x: The number to check
|
|
241
|
+
* @returns `true` if the value is a floating point number or `false` otherwise
|
|
242
|
+
*
|
|
243
|
+
* @since v0.5.3
|
|
244
|
+
*/
|
|
245
|
+
@unsafe
|
|
246
|
+
export let isFloat = (x: Number) => {
|
|
247
|
+
isFloat(WasmI32.fromGrain(x))
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Checks if a number is an integer.
|
|
252
|
+
*
|
|
253
|
+
* @param x: The number to check
|
|
254
|
+
* @returns `true` if the value is an integer or `false` otherwise
|
|
255
|
+
*
|
|
256
|
+
* @since v0.5.3
|
|
257
|
+
*/
|
|
258
|
+
@unsafe
|
|
259
|
+
export let isInteger = (x: Number) => {
|
|
260
|
+
isInteger(WasmI32.fromGrain(x))
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* Checks if a number is a non-integer rational value.
|
|
265
|
+
*
|
|
266
|
+
* @param x: The number to check
|
|
267
|
+
* @returns `true` if the value is a non-integer rational number or `false` otherwise
|
|
268
|
+
*
|
|
269
|
+
* @since v0.5.3
|
|
270
|
+
*/
|
|
271
|
+
@unsafe
|
|
272
|
+
export let isRational = (x: Number) => {
|
|
273
|
+
isRational(WasmI32.fromGrain(x))
|
|
274
|
+
}
|
|
275
|
+
|
|
235
276
|
/**
|
|
236
277
|
* Checks if a number is finite.
|
|
237
278
|
* All values are finite exept for floating point NaN, infinity or negative infinity.
|
package/number.md
CHANGED
|
@@ -20,7 +20,7 @@ Number constant values.
|
|
|
20
20
|
### Number.**pi**
|
|
21
21
|
|
|
22
22
|
<details disabled>
|
|
23
|
-
<summary tabindex="-1">Added in <code>
|
|
23
|
+
<summary tabindex="-1">Added in <code>0.5.2</code></summary>
|
|
24
24
|
No other changes yet.
|
|
25
25
|
</details>
|
|
26
26
|
|
|
@@ -33,7 +33,7 @@ Pi represented as a Number value.
|
|
|
33
33
|
### Number.**tau**
|
|
34
34
|
|
|
35
35
|
<details disabled>
|
|
36
|
-
<summary tabindex="-1">Added in <code>
|
|
36
|
+
<summary tabindex="-1">Added in <code>0.5.2</code></summary>
|
|
37
37
|
No other changes yet.
|
|
38
38
|
</details>
|
|
39
39
|
|
|
@@ -46,7 +46,7 @@ Tau represented as a Number value.
|
|
|
46
46
|
### Number.**e**
|
|
47
47
|
|
|
48
48
|
<details disabled>
|
|
49
|
-
<summary tabindex="-1">Added in <code>
|
|
49
|
+
<summary tabindex="-1">Added in <code>0.5.2</code></summary>
|
|
50
50
|
No other changes yet.
|
|
51
51
|
</details>
|
|
52
52
|
|
|
@@ -425,6 +425,81 @@ Returns:
|
|
|
425
425
|
|----|-----------|
|
|
426
426
|
|`Number`|The negated operand|
|
|
427
427
|
|
|
428
|
+
### Number.**isFloat**
|
|
429
|
+
|
|
430
|
+
<details disabled>
|
|
431
|
+
<summary tabindex="-1">Added in <code>0.5.3</code></summary>
|
|
432
|
+
No other changes yet.
|
|
433
|
+
</details>
|
|
434
|
+
|
|
435
|
+
```grain
|
|
436
|
+
isFloat : Number -> Bool
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
Checks if a number is a floating point value.
|
|
440
|
+
|
|
441
|
+
Parameters:
|
|
442
|
+
|
|
443
|
+
|param|type|description|
|
|
444
|
+
|-----|----|-----------|
|
|
445
|
+
|`x`|`Number`|The number to check|
|
|
446
|
+
|
|
447
|
+
Returns:
|
|
448
|
+
|
|
449
|
+
|type|description|
|
|
450
|
+
|----|-----------|
|
|
451
|
+
|`Bool`|`true` if the value is a floating point number or `false` otherwise|
|
|
452
|
+
|
|
453
|
+
### Number.**isInteger**
|
|
454
|
+
|
|
455
|
+
<details disabled>
|
|
456
|
+
<summary tabindex="-1">Added in <code>0.5.3</code></summary>
|
|
457
|
+
No other changes yet.
|
|
458
|
+
</details>
|
|
459
|
+
|
|
460
|
+
```grain
|
|
461
|
+
isInteger : Number -> Bool
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
Checks if a number is an integer.
|
|
465
|
+
|
|
466
|
+
Parameters:
|
|
467
|
+
|
|
468
|
+
|param|type|description|
|
|
469
|
+
|-----|----|-----------|
|
|
470
|
+
|`x`|`Number`|The number to check|
|
|
471
|
+
|
|
472
|
+
Returns:
|
|
473
|
+
|
|
474
|
+
|type|description|
|
|
475
|
+
|----|-----------|
|
|
476
|
+
|`Bool`|`true` if the value is an integer or `false` otherwise|
|
|
477
|
+
|
|
478
|
+
### Number.**isRational**
|
|
479
|
+
|
|
480
|
+
<details disabled>
|
|
481
|
+
<summary tabindex="-1">Added in <code>0.5.3</code></summary>
|
|
482
|
+
No other changes yet.
|
|
483
|
+
</details>
|
|
484
|
+
|
|
485
|
+
```grain
|
|
486
|
+
isRational : Number -> Bool
|
|
487
|
+
```
|
|
488
|
+
|
|
489
|
+
Checks if a number is a non-integer rational value.
|
|
490
|
+
|
|
491
|
+
Parameters:
|
|
492
|
+
|
|
493
|
+
|param|type|description|
|
|
494
|
+
|-----|----|-----------|
|
|
495
|
+
|`x`|`Number`|The number to check|
|
|
496
|
+
|
|
497
|
+
Returns:
|
|
498
|
+
|
|
499
|
+
|type|description|
|
|
500
|
+
|----|-----------|
|
|
501
|
+
|`Bool`|`true` if the value is a non-integer rational number or `false` otherwise|
|
|
502
|
+
|
|
428
503
|
### Number.**isFinite**
|
|
429
504
|
|
|
430
505
|
<details disabled>
|
|
@@ -538,7 +613,7 @@ Returns:
|
|
|
538
613
|
### Number.**sin**
|
|
539
614
|
|
|
540
615
|
<details disabled>
|
|
541
|
-
<summary tabindex="-1">Added in <code>
|
|
616
|
+
<summary tabindex="-1">Added in <code>0.5.2</code></summary>
|
|
542
617
|
No other changes yet.
|
|
543
618
|
</details>
|
|
544
619
|
|
|
@@ -563,7 +638,7 @@ Returns:
|
|
|
563
638
|
### Number.**cos**
|
|
564
639
|
|
|
565
640
|
<details disabled>
|
|
566
|
-
<summary tabindex="-1">Added in <code>
|
|
641
|
+
<summary tabindex="-1">Added in <code>0.5.2</code></summary>
|
|
567
642
|
No other changes yet.
|
|
568
643
|
</details>
|
|
569
644
|
|
package/package.json
CHANGED
package/pervasives.gr
CHANGED
|
@@ -11,6 +11,7 @@ import Memory from "runtime/unsafe/memory"
|
|
|
11
11
|
import WasmI32 from "runtime/unsafe/wasmi32"
|
|
12
12
|
|
|
13
13
|
import { equal as (==) } from "runtime/equal"
|
|
14
|
+
import { compare } from "runtime/compare"
|
|
14
15
|
|
|
15
16
|
import {
|
|
16
17
|
incr,
|
|
@@ -218,6 +219,19 @@ export (<=)
|
|
|
218
219
|
*/
|
|
219
220
|
export (>=)
|
|
220
221
|
|
|
222
|
+
/**
|
|
223
|
+
* Compares the first argument to the second argument and produces an integer result.
|
|
224
|
+
* Provides a consistent ordering over all types and is suitable for sorting and other kinds of ordering.
|
|
225
|
+
* `compare` treats `NaN` differently than the other comparison operators in that it considers `NaN` equal to itself and smaller than any other number.
|
|
226
|
+
*
|
|
227
|
+
* @param num1: The first operand
|
|
228
|
+
* @param num2: The second operand
|
|
229
|
+
* @returns A negative integer if the first operand is less than the second operand, `0` if they are equal, or a positive integer otherwise
|
|
230
|
+
*
|
|
231
|
+
* @since v0.5.3
|
|
232
|
+
*/
|
|
233
|
+
export compare
|
|
234
|
+
|
|
221
235
|
/**
|
|
222
236
|
* @section Math operations: Infix functions for working with Number values.
|
|
223
237
|
*/
|
|
@@ -410,7 +424,7 @@ export (>>)
|
|
|
410
424
|
|
|
411
425
|
// Number coercions & conversions
|
|
412
426
|
|
|
413
|
-
//
|
|
427
|
+
// TODO(#311): Commented until we nail down semantics
|
|
414
428
|
// import foreign wasm convertExactToInexact : Number -> Number as inexact from "stdlib-external/runtime"
|
|
415
429
|
// import foreign wasm convertInexactToExact : Number -> Number as exact from "stdlib-external/runtime"
|
|
416
430
|
|
|
@@ -553,10 +567,7 @@ export primitive unbox: Box<a> -> a = "@unbox"
|
|
|
553
567
|
* @since v0.4.0
|
|
554
568
|
*/
|
|
555
569
|
export let cons = (a, b) =>
|
|
556
|
-
[
|
|
557
|
-
a,
|
|
558
|
-
...b
|
|
559
|
-
] // <- workaround for (grain-lang/grain#802) [TODO] fix #802 and delete
|
|
570
|
+
[a, ...b] // TODO(#802): Remove workaround after 802 is completed
|
|
560
571
|
/**
|
|
561
572
|
* The empty list syntax (`[]`) provided as a value.
|
|
562
573
|
*
|
package/pervasives.md
CHANGED
|
@@ -369,6 +369,34 @@ Returns:
|
|
|
369
369
|
|----|-----------|
|
|
370
370
|
|`Bool`|`true` if the first operand is greater than or equal to the second operand or `false` otherwise|
|
|
371
371
|
|
|
372
|
+
### Pervasives.**compare**
|
|
373
|
+
|
|
374
|
+
<details disabled>
|
|
375
|
+
<summary tabindex="-1">Added in <code>0.5.3</code></summary>
|
|
376
|
+
No other changes yet.
|
|
377
|
+
</details>
|
|
378
|
+
|
|
379
|
+
```grain
|
|
380
|
+
compare : (a, a) -> Number
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
Compares the first argument to the second argument and produces an integer result.
|
|
384
|
+
Provides a consistent ordering over all types and is suitable for sorting and other kinds of ordering.
|
|
385
|
+
`compare` treats `NaN` differently than the other comparison operators in that it considers `NaN` equal to itself and smaller than any other number.
|
|
386
|
+
|
|
387
|
+
Parameters:
|
|
388
|
+
|
|
389
|
+
|param|type|description|
|
|
390
|
+
|-----|----|-----------|
|
|
391
|
+
|`num1`|`a`|The first operand|
|
|
392
|
+
|`num2`|`a`|The second operand|
|
|
393
|
+
|
|
394
|
+
Returns:
|
|
395
|
+
|
|
396
|
+
|type|description|
|
|
397
|
+
|----|-----------|
|
|
398
|
+
|`Number`|A negative integer if the first operand is less than the second operand, `0` if they are equal, or a positive integer otherwise|
|
|
399
|
+
|
|
372
400
|
## Math operations
|
|
373
401
|
|
|
374
402
|
Infix functions for working with Number values.
|
package/priorityqueue.gr
ADDED
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module PriorityQueue: A mutable priority queue implementation. A priority queue is a data structure that maintains elements in a priority order. Elements with higher priority are served before elements with lower priority when extracting from the priority queue.
|
|
3
|
+
*
|
|
4
|
+
* @example import PriorityQueue from "priorityqueue"
|
|
5
|
+
*
|
|
6
|
+
* @since v0.5.3
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import Array from "array"
|
|
10
|
+
import List from "list"
|
|
11
|
+
import Number from "number"
|
|
12
|
+
import Option from "option"
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @section Types: Type declarations included in the PriorityQueue module.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Mutable data structure which maintains a priority order for its elements.
|
|
20
|
+
*/
|
|
21
|
+
record PriorityQueue<a> {
|
|
22
|
+
mut size: Number,
|
|
23
|
+
mut array: Array<Option<a>>,
|
|
24
|
+
comp: (a, a) -> Number,
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* @section Values: Functions for working with PriorityQueues.
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
let swap = (i1, i2, array) => {
|
|
32
|
+
let t = array[i2]
|
|
33
|
+
array[i2] = array[i1]
|
|
34
|
+
array[i1] = t
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
let get = (array, i) =>
|
|
38
|
+
Option.expect(
|
|
39
|
+
"Impossible: " ++
|
|
40
|
+
toString(i) ++
|
|
41
|
+
" in PriorityQueue's inner storage array is None",
|
|
42
|
+
array[i]
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
let rec siftDown = (i, pq) => {
|
|
46
|
+
let leftI = 2 * i + 1
|
|
47
|
+
let rightI = 2 * i + 2
|
|
48
|
+
|
|
49
|
+
// we want to find the smaller child from the current tree node to sift down to
|
|
50
|
+
let mut swapWithI = i
|
|
51
|
+
if (leftI < pq.size && pq.comp(get(pq.array, leftI), get(pq.array, i)) < 0) {
|
|
52
|
+
swapWithI = leftI
|
|
53
|
+
}
|
|
54
|
+
if (
|
|
55
|
+
rightI < pq.size &&
|
|
56
|
+
pq.comp(get(pq.array, rightI), get(pq.array, swapWithI)) < 0
|
|
57
|
+
) {
|
|
58
|
+
swapWithI = rightI
|
|
59
|
+
}
|
|
60
|
+
if (swapWithI != i) {
|
|
61
|
+
swap(i, swapWithI, pq.array)
|
|
62
|
+
siftDown(swapWithI, pq)
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
let rec siftUp = (i, pq) => {
|
|
67
|
+
let parentI = Number.trunc((i - 1) / 2)
|
|
68
|
+
// we should only sift up if the element is smaller than its parent
|
|
69
|
+
if (i > 0 && pq.comp(get(pq.array, i), get(pq.array, parentI)) < 0) {
|
|
70
|
+
swap(i, parentI, pq.array)
|
|
71
|
+
siftUp(parentI, pq)
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Creates a new priority queue with a given internal storage size and a
|
|
77
|
+
* comparator function, which is used to determine priority of elements. The
|
|
78
|
+
* comparator function takes two elements and must return 0 if both share
|
|
79
|
+
* priority, a positive number if the first has greater priority, and a
|
|
80
|
+
* negative number if the first has less priority.
|
|
81
|
+
*
|
|
82
|
+
* Generally, you won't need to care about the storage size of your priority
|
|
83
|
+
* queue and can use `PriorityQueue.make()` instead.
|
|
84
|
+
*
|
|
85
|
+
* @param size: The initial storage size of the priority queue
|
|
86
|
+
* @param comp: The comparator function used to indicate priority order
|
|
87
|
+
* @returns An empty priority queue
|
|
88
|
+
*
|
|
89
|
+
* @since v0.5.3
|
|
90
|
+
*/
|
|
91
|
+
export let makeSized = (size, comp) => {
|
|
92
|
+
{ size: 0, array: Array.make(size, None), comp }
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Creates a new priority queue with a comparator function, which is used to
|
|
97
|
+
* determine priority of elements. The comparator function takes two elements
|
|
98
|
+
* and must return 0 if both share priority, a positive number if the first
|
|
99
|
+
* has greater priority, and a negative number if the first has less priority.
|
|
100
|
+
*
|
|
101
|
+
* @param comp: The comparator function used to indicate priority order
|
|
102
|
+
* @returns An empty priority queue
|
|
103
|
+
*
|
|
104
|
+
* @example PriorityQueue.make(compare) // creates a min priority queue of numbers using the compare pervasive
|
|
105
|
+
* @example PriorityQueue.make((a, b) => String.length(b) - String.length(a)) // creates a priority queue by string length (longest to shortest)
|
|
106
|
+
*
|
|
107
|
+
* @since v0.5.3
|
|
108
|
+
*/
|
|
109
|
+
export let make = comp => {
|
|
110
|
+
makeSized(16, comp)
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Gets the number of elements in a priority queue.
|
|
115
|
+
*
|
|
116
|
+
* @param pq: The priority queue to inspect
|
|
117
|
+
* @returns The number of elements in the priority queue
|
|
118
|
+
*
|
|
119
|
+
* @since v0.5.3
|
|
120
|
+
*/
|
|
121
|
+
export let size = pq => {
|
|
122
|
+
pq.size
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Determines if the priority queue contains no elements.
|
|
127
|
+
*
|
|
128
|
+
* @param pq: The priority queue to check
|
|
129
|
+
* @returns `true` if the priority queue is empty and `false` otherwise
|
|
130
|
+
*
|
|
131
|
+
* @since v0.5.3
|
|
132
|
+
*/
|
|
133
|
+
export let isEmpty = pq => {
|
|
134
|
+
pq.size == 0
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Adds a new element to the priority queue.
|
|
139
|
+
*
|
|
140
|
+
* @param val: The value to add into the priority queue
|
|
141
|
+
* @param pq: The priority queue to update
|
|
142
|
+
*
|
|
143
|
+
* @since v0.5.3
|
|
144
|
+
*/
|
|
145
|
+
export let push = (val, pq) => {
|
|
146
|
+
let arrLen = Array.length(pq.array)
|
|
147
|
+
// double size of internal array if out of space
|
|
148
|
+
if (pq.size == arrLen) {
|
|
149
|
+
let oldArr = pq.array
|
|
150
|
+
pq.array = Array.make(arrLen * 2, None)
|
|
151
|
+
Array.forEachi((val, i) => {
|
|
152
|
+
pq.array[i] = val
|
|
153
|
+
}, oldArr)
|
|
154
|
+
}
|
|
155
|
+
pq.array[pq.size] = Some(val)
|
|
156
|
+
pq.size += 1
|
|
157
|
+
// reorder heap to ensure that binary heap property of parent nodes having
|
|
158
|
+
// larger values than their children is upheld
|
|
159
|
+
siftUp(pq.size - 1, pq)
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Retrieves the highest priority element in the priority queue. It is not
|
|
164
|
+
* removed from the queue.
|
|
165
|
+
*
|
|
166
|
+
* @param pq: The priority queue to inspect
|
|
167
|
+
* @returns `Some(value)` containing the highest priority element or `None` if the priority queue is empty
|
|
168
|
+
*
|
|
169
|
+
* @since v0.5.3
|
|
170
|
+
*/
|
|
171
|
+
export let peek = pq => {
|
|
172
|
+
if (pq.size == 0) {
|
|
173
|
+
None
|
|
174
|
+
} else {
|
|
175
|
+
pq.array[0]
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Removes and retrieves the highest priority element in the priority queue.
|
|
181
|
+
*
|
|
182
|
+
* @param pq: The priority queue to inspect
|
|
183
|
+
* @returns `Some(value)` containing the highest priority element or `None` if the priority queue is empty
|
|
184
|
+
*
|
|
185
|
+
* @since v0.5.3
|
|
186
|
+
*/
|
|
187
|
+
export let pop = pq => {
|
|
188
|
+
if (pq.size == 0) {
|
|
189
|
+
None
|
|
190
|
+
} else {
|
|
191
|
+
let root = pq.array[0]
|
|
192
|
+
|
|
193
|
+
pq.array[0] = pq.array[pq.size - 1]
|
|
194
|
+
pq.array[pq.size - 1] = None
|
|
195
|
+
pq.size -= 1
|
|
196
|
+
// reorder heap to ensure that binary heap property of parent nodes having
|
|
197
|
+
// larger values than their children is upheld
|
|
198
|
+
siftDown(0, pq)
|
|
199
|
+
root
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Clears the priority queue and produces a list of all of the elements in the priority
|
|
205
|
+
* queue in priority order.
|
|
206
|
+
*
|
|
207
|
+
* @param pq: The priority queue to drain
|
|
208
|
+
* @returns A list of all elements in the priority in priority order
|
|
209
|
+
*
|
|
210
|
+
* @since v0.5.3
|
|
211
|
+
*/
|
|
212
|
+
export let drain = pq => {
|
|
213
|
+
let rec drainRec = acc => {
|
|
214
|
+
match (pop(pq)) {
|
|
215
|
+
Some(val) => drainRec([val, ...acc]),
|
|
216
|
+
None => acc,
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
List.reverse(drainRec([]))
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Constructs a new priority queue initialized with the elements in the list
|
|
224
|
+
* using a custom comparator function, which is used to determine priority of
|
|
225
|
+
* elements. The comparator function takes two elements and must return 0 if
|
|
226
|
+
* both share priority, a positive number if the first has greater priority,
|
|
227
|
+
* and a negative number if the first has less priority.
|
|
228
|
+
*
|
|
229
|
+
* @param list: A list of values used to initialize the priority queue
|
|
230
|
+
* @param comp: A comparator function used to assign priority to elements
|
|
231
|
+
* @returns A priority queue containing the elements from the list
|
|
232
|
+
*
|
|
233
|
+
* @since v0.5.3
|
|
234
|
+
*/
|
|
235
|
+
export let fromList = (list, comp) => {
|
|
236
|
+
let heap = makeSized(List.length(list), comp)
|
|
237
|
+
List.forEach(val => {
|
|
238
|
+
push(val, heap)
|
|
239
|
+
}, list)
|
|
240
|
+
heap
|
|
241
|
+
}
|