@grain/stdlib 0.5.0 → 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.
@@ -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
+ }
@@ -0,0 +1,279 @@
1
+ ---
2
+ title: PriorityQueue
3
+ ---
4
+
5
+ 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.
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 PriorityQueue from "priorityqueue"
14
+ ```
15
+
16
+ ## Types
17
+
18
+ Type declarations included in the PriorityQueue module.
19
+
20
+ ### PriorityQueue.**PriorityQueue**
21
+
22
+ ```grain
23
+ type PriorityQueue<a>
24
+ ```
25
+
26
+ Mutable data structure which maintains a priority order for its elements.
27
+
28
+ ## Values
29
+
30
+ Functions for working with PriorityQueues.
31
+
32
+ ### PriorityQueue.**makeSized**
33
+
34
+ <details disabled>
35
+ <summary tabindex="-1">Added in <code>0.5.3</code></summary>
36
+ No other changes yet.
37
+ </details>
38
+
39
+ ```grain
40
+ makeSized : (Number, ((a, a) -> Number)) -> PriorityQueue<a>
41
+ ```
42
+
43
+ Creates a new priority queue with a given internal storage size and a
44
+ comparator function, which is used to determine priority of elements. The
45
+ comparator function takes two elements and must return 0 if both share
46
+ priority, a positive number if the first has greater priority, and a
47
+ negative number if the first has less priority.
48
+
49
+ Generally, you won't need to care about the storage size of your priority
50
+ queue and can use `PriorityQueue.make()` instead.
51
+
52
+ Parameters:
53
+
54
+ |param|type|description|
55
+ |-----|----|-----------|
56
+ |`size`|`Number`|The initial storage size of the priority queue|
57
+ |`comp`|`(a, a) -> Number`|The comparator function used to indicate priority order|
58
+
59
+ Returns:
60
+
61
+ |type|description|
62
+ |----|-----------|
63
+ |`PriorityQueue<a>`|An empty priority queue|
64
+
65
+ ### PriorityQueue.**make**
66
+
67
+ <details disabled>
68
+ <summary tabindex="-1">Added in <code>0.5.3</code></summary>
69
+ No other changes yet.
70
+ </details>
71
+
72
+ ```grain
73
+ make : ((a, a) -> Number) -> PriorityQueue<a>
74
+ ```
75
+
76
+ Creates a new priority queue with a comparator function, which is used to
77
+ determine priority of elements. The comparator function takes two elements
78
+ and must return 0 if both share priority, a positive number if the first
79
+ has greater priority, and a negative number if the first has less priority.
80
+
81
+ Parameters:
82
+
83
+ |param|type|description|
84
+ |-----|----|-----------|
85
+ |`comp`|`(a, a) -> Number`|The comparator function used to indicate priority order|
86
+
87
+ Returns:
88
+
89
+ |type|description|
90
+ |----|-----------|
91
+ |`PriorityQueue<a>`|An empty priority queue|
92
+
93
+ Examples:
94
+
95
+ ```grain
96
+ PriorityQueue.make(compare) // creates a min priority queue of numbers using the compare pervasive
97
+ ```
98
+
99
+ ```grain
100
+ PriorityQueue.make((a, b) => String.length(b) - String.length(a)) // creates a priority queue by string length (longest to shortest)
101
+ ```
102
+
103
+ ### PriorityQueue.**size**
104
+
105
+ <details disabled>
106
+ <summary tabindex="-1">Added in <code>0.5.3</code></summary>
107
+ No other changes yet.
108
+ </details>
109
+
110
+ ```grain
111
+ size : PriorityQueue<a> -> Number
112
+ ```
113
+
114
+ Gets the number of elements in a priority queue.
115
+
116
+ Parameters:
117
+
118
+ |param|type|description|
119
+ |-----|----|-----------|
120
+ |`pq`|`PriorityQueue<a>`|The priority queue to inspect|
121
+
122
+ Returns:
123
+
124
+ |type|description|
125
+ |----|-----------|
126
+ |`Number`|The number of elements in the priority queue|
127
+
128
+ ### PriorityQueue.**isEmpty**
129
+
130
+ <details disabled>
131
+ <summary tabindex="-1">Added in <code>0.5.3</code></summary>
132
+ No other changes yet.
133
+ </details>
134
+
135
+ ```grain
136
+ isEmpty : PriorityQueue<a> -> Bool
137
+ ```
138
+
139
+ Determines if the priority queue contains no elements.
140
+
141
+ Parameters:
142
+
143
+ |param|type|description|
144
+ |-----|----|-----------|
145
+ |`pq`|`PriorityQueue<a>`|The priority queue to check|
146
+
147
+ Returns:
148
+
149
+ |type|description|
150
+ |----|-----------|
151
+ |`Bool`|`true` if the priority queue is empty and `false` otherwise|
152
+
153
+ ### PriorityQueue.**push**
154
+
155
+ <details disabled>
156
+ <summary tabindex="-1">Added in <code>0.5.3</code></summary>
157
+ No other changes yet.
158
+ </details>
159
+
160
+ ```grain
161
+ push : (a, PriorityQueue<a>) -> Void
162
+ ```
163
+
164
+ Adds a new element to the priority queue.
165
+
166
+ Parameters:
167
+
168
+ |param|type|description|
169
+ |-----|----|-----------|
170
+ |`val`|`a`|The value to add into the priority queue|
171
+ |`pq`|`PriorityQueue<a>`|The priority queue to update|
172
+
173
+ ### PriorityQueue.**peek**
174
+
175
+ <details disabled>
176
+ <summary tabindex="-1">Added in <code>0.5.3</code></summary>
177
+ No other changes yet.
178
+ </details>
179
+
180
+ ```grain
181
+ peek : PriorityQueue<a> -> Option<a>
182
+ ```
183
+
184
+ Retrieves the highest priority element in the priority queue. It is not
185
+ removed from the queue.
186
+
187
+ Parameters:
188
+
189
+ |param|type|description|
190
+ |-----|----|-----------|
191
+ |`pq`|`PriorityQueue<a>`|The priority queue to inspect|
192
+
193
+ Returns:
194
+
195
+ |type|description|
196
+ |----|-----------|
197
+ |`Option<a>`|`Some(value)` containing the highest priority element or `None` if the priority queue is empty|
198
+
199
+ ### PriorityQueue.**pop**
200
+
201
+ <details disabled>
202
+ <summary tabindex="-1">Added in <code>0.5.3</code></summary>
203
+ No other changes yet.
204
+ </details>
205
+
206
+ ```grain
207
+ pop : PriorityQueue<a> -> Option<a>
208
+ ```
209
+
210
+ Removes and retrieves the highest priority element in the priority queue.
211
+
212
+ Parameters:
213
+
214
+ |param|type|description|
215
+ |-----|----|-----------|
216
+ |`pq`|`PriorityQueue<a>`|The priority queue to inspect|
217
+
218
+ Returns:
219
+
220
+ |type|description|
221
+ |----|-----------|
222
+ |`Option<a>`|`Some(value)` containing the highest priority element or `None` if the priority queue is empty|
223
+
224
+ ### PriorityQueue.**drain**
225
+
226
+ <details disabled>
227
+ <summary tabindex="-1">Added in <code>0.5.3</code></summary>
228
+ No other changes yet.
229
+ </details>
230
+
231
+ ```grain
232
+ drain : PriorityQueue<a> -> List<a>
233
+ ```
234
+
235
+ Clears the priority queue and produces a list of all of the elements in the priority
236
+ queue in priority order.
237
+
238
+ Parameters:
239
+
240
+ |param|type|description|
241
+ |-----|----|-----------|
242
+ |`pq`|`PriorityQueue<a>`|The priority queue to drain|
243
+
244
+ Returns:
245
+
246
+ |type|description|
247
+ |----|-----------|
248
+ |`List<a>`|A list of all elements in the priority in priority order|
249
+
250
+ ### PriorityQueue.**fromList**
251
+
252
+ <details disabled>
253
+ <summary tabindex="-1">Added in <code>0.5.3</code></summary>
254
+ No other changes yet.
255
+ </details>
256
+
257
+ ```grain
258
+ fromList : (List<a>, ((a, a) -> Number)) -> PriorityQueue<a>
259
+ ```
260
+
261
+ Constructs a new priority queue initialized with the elements in the list
262
+ using a custom comparator function, which is used to determine priority of
263
+ elements. The comparator function takes two elements and must return 0 if
264
+ both share priority, a positive number if the first has greater priority,
265
+ and a negative number if the first has less priority.
266
+
267
+ Parameters:
268
+
269
+ |param|type|description|
270
+ |-----|----|-----------|
271
+ |`list`|`List<a>`|A list of values used to initialize the priority queue|
272
+ |`comp`|`(a, a) -> Number`|A comparator function used to assign priority to elements|
273
+
274
+ Returns:
275
+
276
+ |type|description|
277
+ |----|-----------|
278
+ |`PriorityQueue<a>`|A priority queue containing the elements from the list|
279
+
package/random.md CHANGED
@@ -5,7 +5,7 @@ title: Random
5
5
  Pseudo-random number generation.
6
6
 
7
7
  <details disabled>
8
- <summary tabindex="-1">Added in <code>next</code></summary>
8
+ <summary tabindex="-1">Added in <code>0.5.0</code></summary>
9
9
  No other changes yet.
10
10
  </details>
11
11
 
@@ -30,7 +30,7 @@ Functions for working with pseudo-random number generators.
30
30
  ### Random.**make**
31
31
 
32
32
  <details disabled>
33
- <summary tabindex="-1">Added in <code>next</code></summary>
33
+ <summary tabindex="-1">Added in <code>0.5.0</code></summary>
34
34
  No other changes yet.
35
35
  </details>
36
36
 
@@ -55,7 +55,7 @@ Returns:
55
55
  ### Random.**makeUnseeded**
56
56
 
57
57
  <details disabled>
58
- <summary tabindex="-1">Added in <code>next</code></summary>
58
+ <summary tabindex="-1">Added in <code>0.5.0</code></summary>
59
59
  No other changes yet.
60
60
  </details>
61
61
 
@@ -74,7 +74,7 @@ Returns:
74
74
  ### Random.**nextInt32**
75
75
 
76
76
  <details disabled>
77
- <summary tabindex="-1">Added in <code>next</code></summary>
77
+ <summary tabindex="-1">Added in <code>0.5.0</code></summary>
78
78
  No other changes yet.
79
79
  </details>
80
80
 
@@ -99,7 +99,7 @@ Returns:
99
99
  ### Random.**nextInt64**
100
100
 
101
101
  <details disabled>
102
- <summary tabindex="-1">Added in <code>next</code></summary>
102
+ <summary tabindex="-1">Added in <code>0.5.0</code></summary>
103
103
  No other changes yet.
104
104
  </details>
105
105
 
@@ -124,7 +124,7 @@ Returns:
124
124
  ### Random.**nextInt32InRange**
125
125
 
126
126
  <details disabled>
127
- <summary tabindex="-1">Added in <code>next</code></summary>
127
+ <summary tabindex="-1">Added in <code>0.5.0</code></summary>
128
128
  No other changes yet.
129
129
  </details>
130
130
 
@@ -152,7 +152,7 @@ Returns:
152
152
  ### Random.**nextInt64InRange**
153
153
 
154
154
  <details disabled>
155
- <summary tabindex="-1">Added in <code>next</code></summary>
155
+ <summary tabindex="-1">Added in <code>0.5.0</code></summary>
156
156
  No other changes yet.
157
157
  </details>
158
158
 
package/regex.gr CHANGED
@@ -487,7 +487,7 @@ enum MergeMode {
487
487
  }
488
488
 
489
489
  let mergeAdjacent = lst => {
490
- // see [TODO] below
490
+ // TODO: see below
491
491
  let readyForAccum = (l, mode) => {
492
492
  match (l) {
493
493
  [] => true,
@@ -512,7 +512,7 @@ let mergeAdjacent = lst => {
512
512
  // drop empty elements
513
513
  [REEmpty, ...tl] => loop(mode, accum, tl),
514
514
  [RELiteralString(""), ...tl] => loop(mode, accum, tl),
515
- // [TODO] Clean up with or-patterns (grain-lang/grain#696)
515
+ // TODO(#696): Clean up with or-patterns
516
516
  _ when readyForAccum(l, mode) => {
517
517
  match (accum) {
518
518
  [] => [],
@@ -592,7 +592,7 @@ REGEX PARSING DEFINITIONS
592
592
 
593
593
  // Range parsing ("[a-z]")
594
594
 
595
- // [TODO] (#769) When byte-based regexes are supported, we'll need another limit of 255 for those.
595
+ // TODO(#769): When byte-based regexes are supported, we'll need another limit of 255 for those.
596
596
  let rangeLimit = 0x10FFFF
597
597
 
598
598
  // These are snake-cased to avoid confusion with their capitalized counterparts
@@ -1578,7 +1578,7 @@ let rec parseAtom = (buf: RegExBuf) => {
1578
1578
  Err(
1579
1579
  parseErr(buf, "unmatched `" ++ Char.toString(c) ++ "` in pattern", 0)
1580
1580
  ),
1581
- // [TODO] case-insensitive (#691)
1581
+ // TODO(#691): Enable case-insensitive regular expression matching
1582
1582
  Ok(c) when buf.config.caseSensitive => {
1583
1583
  ignore(next(buf))
1584
1584
  Ok(RELiteral(c))
@@ -3320,7 +3320,7 @@ record RegularExpression {
3320
3320
  * @section Values: Functions for working with regular expressions.
3321
3321
  */
3322
3322
 
3323
- // [TODO] When #661 is resolved, re-add the following pieces of documentation:
3323
+ // TODO(#661): re-add the following pieces of documentation:
3324
3324
  /*
3325
3325
  [Under POSIX character classes]
3326
3326