@grain/stdlib 0.4.0 → 0.4.4

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/option.gr CHANGED
@@ -1,78 +1,195 @@
1
- // Standard library for option functionality
1
+ /**
2
+ * @module Option: Utilities for working with the Option data type.
3
+ *
4
+ * The Option type is an enum that represents the possibility of something being present (with the `Some` variant), or not (with the `None` variant). There’s no standalone `null` or `nil` type in Grain; use an Option where you would normally reach for `null` or `nil`.
5
+ *
6
+ * @example import Option from "option"
7
+ *
8
+ * @example let hasValue = Some(1234) // Creates an Option containing 1234
9
+ * @example let noValue = None // Creates an Option containing nothing
10
+ *
11
+ * @since v0.2.0
12
+ */
2
13
 
3
- export *
14
+ /**
15
+ * @section Values: Functions for working with the Option data type.
16
+ */
4
17
 
5
- let isSome = (option) => {
18
+ /**
19
+ * Checks if the Option is the `Some` variant.
20
+ *
21
+ * @param option: The option to check
22
+ * @returns `true` if the Option is the `Some` variant or `false` otherwise
23
+ *
24
+ * @since v0.2.0
25
+ */
26
+ export let isSome = (option) => {
6
27
  match (option) {
7
28
  Some(_) => true,
8
29
  None => false
9
30
  }
10
31
  }
11
32
 
12
- let isNone = (option) => {
33
+ /**
34
+ * Checks if the Option is the `None` variant.
35
+ *
36
+ * @param option: The option to check
37
+ * @returns `true` if the Option is the `None` variant or `false` otherwise
38
+ *
39
+ * @since v0.2.0
40
+ */
41
+ export let isNone = (option) => {
13
42
  match (option) {
14
43
  None => true,
15
44
  Some(_) => false
16
45
  }
17
46
  }
18
47
 
19
- let contains = (val, option) => {
48
+ /**
49
+ * Checks if the Option is the `Some` variant and contains the given value. Uses the generic `==` equality operator.
50
+ *
51
+ * @param value: The value to search for
52
+ * @param option: The option to search
53
+ * @returns `true` if the Option is equivalent to `Some(value)` or `false` otherwise
54
+ *
55
+ * @since v0.2.0
56
+ */
57
+ export let contains = (value, option) => {
20
58
  match (option) {
21
- Some(x) => x == val,
59
+ Some(x) => x == value,
22
60
  None => false
23
61
  }
24
62
  }
25
63
 
26
- let expect = (msg, option) => {
64
+ /**
65
+ * Extracts the value inside a `Some` option, otherwise throws an
66
+ * exception containing the message provided.
67
+ *
68
+ * @param msg: The message to use upon failure
69
+ * @param option: The option to extract a value from
70
+ * @returns The unwrapped value if the Option is the `Some` variant
71
+ *
72
+ * @since v0.2.0
73
+ */
74
+ export let expect = (msg, option) => {
27
75
  match (option) {
28
76
  Some(x) => x,
29
77
  None => fail msg
30
78
  }
31
79
  }
32
80
 
33
- let unwrap = (option) => {
81
+ /**
82
+ * Extracts the value inside a `Some` option, otherwise
83
+ * throws an exception containing a default message.
84
+ *
85
+ * @param option: The option to extract the value from
86
+ * @returns The unwrapped value if the Option is the `Some` variant
87
+ *
88
+ * @since v0.2.0
89
+ */
90
+ export let unwrap = (option) => {
34
91
  expect("Could not unwrap None value", option)
35
92
  }
36
93
 
37
- let unwrapWithDefault = (default, option) => {
94
+ /**
95
+ * Extracts the value inside a `Some` option or provide the default value if `None`.
96
+ *
97
+ * @param default: The default value
98
+ * @param option: The option to unwrap
99
+ * @returns The unwrapped value if the Option is the `Some` variant or the default value otherwise
100
+ *
101
+ * @since v0.2.0
102
+ */
103
+ export let unwrapWithDefault = (default, option) => {
38
104
  match (option) {
39
105
  Some(x) => x,
40
106
  None => default
41
107
  }
42
108
  }
43
109
 
44
- let map = (fn, option) => {
110
+ /**
111
+ * If the Option is `Some(value)`, applies the given function to the `value` and wraps the new value in a `Some` variant.
112
+ *
113
+ * @param fn: The function to call on the value of a `Some` variant
114
+ * @param option: The option to map
115
+ * @returns A new `Some` variant produced by the mapping function if the variant was `Some` or the unmodified `None` otherwise
116
+ *
117
+ * @since v0.2.0
118
+ */
119
+ export let map = (fn, option) => {
45
120
  match (option) {
46
121
  Some(x) => Some(fn(x)),
47
122
  None => None
48
123
  }
49
124
  }
50
125
 
51
- let mapWithDefault = (fn, default, option) => {
126
+ /**
127
+ * If the Option is `Some(value)`, applies the given function to the `value` to produce a new value, otherwise uses the default value.
128
+ * Useful for unwrapping an Option while providing a fallback for any `None` variants.
129
+ *
130
+ * @param fn: The function to call on the value of a `Some` variant
131
+ * @param default: A fallback value for a `None` variant
132
+ * @param option: The option to map
133
+ * @returns The value produced by the mapping function if the Option is of the `Some` variant or the default value otherwise
134
+ *
135
+ * @since v0.2.0
136
+ */
137
+ export let mapWithDefault = (fn, default, option) => {
52
138
  match (option) {
53
139
  Some(x) => fn(x),
54
140
  None => default
55
141
  }
56
142
  }
57
143
 
58
- let mapWithDefaultFn = (fn, defaultFn, option) => {
144
+ /**
145
+ * If the Option is `Some(value)`, applies the `fn` function to the `value` to produce a new value.
146
+ * If the Option is `None`, calls the `defaultFn` function to produce a new value.
147
+ * Useful for unwrapping an Option into a value, whether it is `Some` or `None`.
148
+ *
149
+ * @param fn: The function to call on the value of a `Some` variant
150
+ * @param defaultFn: The default function
151
+ * @param option: The option to map
152
+ * @returns The value produced by one of the mapping functions
153
+ *
154
+ * @since v0.2.0
155
+ */
156
+ export let mapWithDefaultFn = (fn, defaultFn, option) => {
59
157
  match (option) {
60
158
  Some(x) => fn(x),
61
159
  None => defaultFn()
62
160
  }
63
161
  }
64
162
 
65
- let flatMap = (fn, option) => {
163
+ /**
164
+ * If the Option is `Some(value)`, applies the given function to the `value` to produce a new Option.
165
+ *
166
+ * @param fn: The function to call on the value of a `Some` variant
167
+ * @param option: The option to map
168
+ * @returns A new Option produced by the mapping function if the variant was `Some` or the unmodified `None` otherwise
169
+ *
170
+ * @since v0.2.0
171
+ */
172
+ export let flatMap = (fn, option) => {
66
173
  match (option) {
67
174
  Some(x) => fn(x),
68
175
  None => None
69
176
  }
70
177
  }
71
178
 
72
- let filter = (pred, option) => {
179
+ /**
180
+ * Converts `Some(value)` variants to `None` variants where the predicate function returns `false`.
181
+ * if the `fn` return `true` returns `Some(value)`, otherwise returns `None`.
182
+ *
183
+ * @param fn: The predicate function to indicate if the option should remain `Some`
184
+ * @param option: The option to inspect
185
+ * @returns `Some(value)` if the variant was `Some` and the predicate returns `true` or `None` otherwise
186
+ *
187
+ * @since v0.2.0
188
+ */
189
+ export let filter = (fn, option) => {
73
190
  match (option) {
74
191
  Some(x) =>
75
- if (pred(x)) {
192
+ if (fn(x)) {
76
193
  Some(x)
77
194
  } else {
78
195
  None
@@ -81,70 +198,160 @@ let filter = (pred, option) => {
81
198
  }
82
199
  }
83
200
 
84
- let zip = (optionA, optionB) => {
201
+ /**
202
+ * Combine two Options into a single Option containing a tuple of their values.
203
+ *
204
+ * @param optionA: The first option to combine
205
+ * @param optionB: The second option to combine
206
+ * @returns `Some((valueA, valueB))` if both Options are `Some` variants or `None` otherwise
207
+ *
208
+ * @since v0.2.0
209
+ */
210
+ export let zip = (optionA, optionB) => {
85
211
  match ((optionA, optionB)) {
86
212
  (Some(a), Some(b)) => Some((a, b)),
87
213
  _ => None
88
214
  }
89
215
  }
90
216
 
91
- let zipWith = (fn, optionA, optionB) => {
217
+ /**
218
+ * Combine two Options into a single Option. The new value is produced by applying the given function to both values.
219
+ *
220
+ * @param fn: The function to generate a new value
221
+ * @param optionA: The first option to combine
222
+ * @param optionB: The second option to combine
223
+ * @returns `Some(newValue)` if both Options are `Some` variants or `None` otherwise
224
+ *
225
+ * @since v0.2.0
226
+ */
227
+ export let zipWith = (fn, optionA, optionB) => {
92
228
  match ((optionA, optionB)) {
93
229
  (Some(a), Some(b)) => Some(fn(a, b)),
94
230
  _ => None
95
231
  }
96
232
  }
97
233
 
98
- let flatten = (option) => {
234
+ /**
235
+ * Flattens nested Options.
236
+ *
237
+ * @param option: The option to flatten
238
+ * @returns `Some(innerValue)` if all nested options were the `Some` variant or `None` otherwise
239
+ *
240
+ * @example Option.flatten(Some(Some(1))) == Some(1)
241
+ *
242
+ * @since v0.2.0
243
+ */
244
+ export let flatten = (option) => {
99
245
  match (option) {
100
246
  Some(Some(x)) => Some(x),
101
247
  _ => None
102
248
  }
103
249
  }
104
250
 
105
- let toList = (option) => {
251
+ /**
252
+ * Converts an Option to a list with either zero or one item.
253
+ *
254
+ * @param option: The option to convert
255
+ * @returns `[value]` if the Option was the `Some` variant or `[]` otherwise
256
+ *
257
+ * @since v0.2.0
258
+ */
259
+ export let toList = (option) => {
106
260
  match (option) {
107
261
  Some(x) => [x],
108
262
  None => []
109
263
  }
110
264
  }
111
265
 
112
- let toArray = (option) => {
266
+ /**
267
+ * Converts an Option to an array with either zero or one item.
268
+ *
269
+ * @param option: The option to convert
270
+ * @returns `[> value]` if the Option was the `Some` variant or `[> ]` otherwise
271
+ *
272
+ * @since v0.2.0
273
+ */
274
+ export let toArray = (option) => {
113
275
  match (option) {
114
276
  Some(x) => [> x],
115
277
  None => [>]
116
278
  }
117
279
  }
118
280
 
119
- let sideEffect = (fn, option) => {
281
+ /**
282
+ * Converts the Option to a Result, using the provided error in case of the `None` variant.
283
+ *
284
+ * @param err: The error to use if the option is `None`
285
+ * @param option: The option to convert
286
+ * @returns `Ok(value)` if the Option is `Some(value)` or `Err(err)` if the Option is `None`
287
+ *
288
+ * @since v0.2.0
289
+ */
290
+ export let toResult = (err, option) => {
291
+ match (option) {
292
+ Some(a) => Ok(a),
293
+ None => Err(err)
294
+ }
295
+ }
296
+
297
+ /**
298
+ * If the Option is `Some(value)`, applies the `fn` function to the `value` without producing a new value.
299
+ *
300
+ * @param fn: The function to call on the value of a `Some` variant
301
+ * @param option: The option to inspect
302
+ *
303
+ * @since v0.2.0
304
+ */
305
+ export let sideEffect = (fn, option) => {
120
306
  match (option) {
121
307
  Some(x) => fn(x),
122
308
  None => void
123
309
  }
124
310
  }
125
311
 
126
- let peek = (fn, option) => {
312
+ /**
313
+ * If the Option is `Some(value)`, applies the `fn` function to the `value` without producing a new value.
314
+ * Useful for inspecting Options without changing anything.
315
+ *
316
+ * @param fn: The function to call on the value of a `Some` variant
317
+ * @param option: The option to inspect
318
+ * @returns The unmodified option
319
+ *
320
+ * @since v0.2.0
321
+ */
322
+ export let peek = (fn, option) => {
127
323
  sideEffect(fn, option)
128
324
  option
129
325
  }
130
326
 
131
- let or = (r1, r2) => {
132
- match (r1) {
133
- Some(x) => r1,
134
- None => r2
327
+ /**
328
+ * Behaves like a logical OR (`||`) where the first Option is only returned if it is the `Some` variant and falling back to the second Option in all other cases.
329
+ *
330
+ * @param optionA: The first option
331
+ * @param optionB: The second option
332
+ * @returns The first Option if it is the `Some` variant or the second Option otherwise
333
+ *
334
+ * @since v0.2.0
335
+ */
336
+ export let or = (optionA, optionB) => {
337
+ match (optionA) {
338
+ Some(x) => optionA,
339
+ None => optionB
135
340
  }
136
341
  }
137
342
 
138
- let and = (r1, r2) => {
139
- match (r1) {
140
- Some(_) => r2,
141
- None => r1
142
- }
143
- }
144
-
145
- let toResult = (err, option) => {
146
- match (option) {
147
- Some(a) => Ok(a),
148
- None => Err(err)
343
+ /**
344
+ * Behaves like a logical AND (`&&`) where the first Option is only returned if it is the `None` variant and falling back to the second Option Result in all other cases.
345
+ *
346
+ * @param optionA: The first option
347
+ * @param optionB: The second option
348
+ * @returns The second Option if both are the `Some` variant or the first Option otherwise
349
+ *
350
+ * @since v0.2.0
351
+ */
352
+ export let and = (optionA, optionB) => {
353
+ match (optionA) {
354
+ Some(_) => optionB,
355
+ None => optionA
149
356
  }
150
357
  }