effect 2.4.16 → 2.4.17

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.
Files changed (69) hide show
  1. package/Iterable/package.json +6 -0
  2. package/dist/cjs/Effect.js +11 -4
  3. package/dist/cjs/Effect.js.map +1 -1
  4. package/dist/cjs/Inspectable.js +23 -1
  5. package/dist/cjs/Inspectable.js.map +1 -1
  6. package/dist/cjs/Iterable.js +938 -0
  7. package/dist/cjs/Iterable.js.map +1 -0
  8. package/dist/cjs/ReadonlyArray.js +2 -17
  9. package/dist/cjs/ReadonlyArray.js.map +1 -1
  10. package/dist/cjs/index.js +4 -2
  11. package/dist/cjs/index.js.map +1 -1
  12. package/dist/cjs/internal/core-effect.js.map +1 -1
  13. package/dist/cjs/internal/effect/circular.js.map +1 -1
  14. package/dist/cjs/internal/fiberRuntime.js +3 -2
  15. package/dist/cjs/internal/fiberRuntime.js.map +1 -1
  16. package/dist/cjs/internal/logger.js +8 -22
  17. package/dist/cjs/internal/logger.js.map +1 -1
  18. package/dist/cjs/internal/runtime.js +42 -50
  19. package/dist/cjs/internal/runtime.js.map +1 -1
  20. package/dist/cjs/internal/schedule.js.map +1 -1
  21. package/dist/cjs/internal/version.js +1 -1
  22. package/dist/dts/Config.d.ts +2 -2
  23. package/dist/dts/Config.d.ts.map +1 -1
  24. package/dist/dts/Effect.d.ts +30 -20
  25. package/dist/dts/Effect.d.ts.map +1 -1
  26. package/dist/dts/Inspectable.d.ts +8 -0
  27. package/dist/dts/Inspectable.d.ts.map +1 -1
  28. package/dist/dts/Iterable.d.ts +495 -0
  29. package/dist/dts/Iterable.d.ts.map +1 -0
  30. package/dist/dts/ReadonlyArray.d.ts.map +1 -1
  31. package/dist/dts/index.d.ts +6 -0
  32. package/dist/dts/index.d.ts.map +1 -1
  33. package/dist/dts/internal/logger.d.ts +0 -1
  34. package/dist/dts/internal/logger.d.ts.map +1 -1
  35. package/dist/esm/Effect.js +7 -0
  36. package/dist/esm/Effect.js.map +1 -1
  37. package/dist/esm/Inspectable.js +20 -0
  38. package/dist/esm/Inspectable.js.map +1 -1
  39. package/dist/esm/Iterable.js +893 -0
  40. package/dist/esm/Iterable.js.map +1 -0
  41. package/dist/esm/ReadonlyArray.js +2 -17
  42. package/dist/esm/ReadonlyArray.js.map +1 -1
  43. package/dist/esm/index.js +6 -0
  44. package/dist/esm/index.js.map +1 -1
  45. package/dist/esm/internal/core-effect.js.map +1 -1
  46. package/dist/esm/internal/effect/circular.js.map +1 -1
  47. package/dist/esm/internal/fiberRuntime.js +3 -2
  48. package/dist/esm/internal/fiberRuntime.js.map +1 -1
  49. package/dist/esm/internal/logger.js +6 -19
  50. package/dist/esm/internal/logger.js.map +1 -1
  51. package/dist/esm/internal/runtime.js +42 -50
  52. package/dist/esm/internal/runtime.js.map +1 -1
  53. package/dist/esm/internal/schedule.js.map +1 -1
  54. package/dist/esm/internal/version.js +1 -1
  55. package/package.json +9 -1
  56. package/src/Config.ts +2 -2
  57. package/src/Effect.ts +64 -47
  58. package/src/Inspectable.ts +30 -0
  59. package/src/Iterable.ts +1009 -0
  60. package/src/ReadonlyArray.ts +2 -20
  61. package/src/index.ts +7 -0
  62. package/src/internal/config.ts +2 -2
  63. package/src/internal/core-effect.ts +11 -9
  64. package/src/internal/effect/circular.ts +19 -7
  65. package/src/internal/fiberRuntime.ts +47 -29
  66. package/src/internal/logger.ts +6 -28
  67. package/src/internal/runtime.ts +45 -52
  68. package/src/internal/schedule.ts +3 -3
  69. package/src/internal/version.ts +1 -1
@@ -0,0 +1,1009 @@
1
+ /**
2
+ * This module provides utility functions for working with Iterables in TypeScript.
3
+ *
4
+ * @since 2.0.0
5
+ */
6
+
7
+ import type { Either } from "./Either.js"
8
+ import * as E from "./Either.js"
9
+ import * as Equal from "./Equal.js"
10
+ import { dual, identity } from "./Function.js"
11
+ import type { Option } from "./Option.js"
12
+ import * as O from "./Option.js"
13
+ import { isBoolean } from "./Predicate.js"
14
+ import type { NonEmptyArray } from "./ReadonlyArray.js"
15
+ import type * as ReadonlyRecord from "./ReadonlyRecord.js"
16
+ import * as Tuple from "./Tuple.js"
17
+ import type { NoInfer } from "./Types.js"
18
+
19
+ /**
20
+ * Return a `Iterable` with element `i` initialized with `f(i)`.
21
+ *
22
+ * If the `length` is not specified, the `Iterable` will be infinite.
23
+ *
24
+ * **Note**. `length` is normalized to an integer >= 1.
25
+ *
26
+ * @example
27
+ * import { makeBy } from 'effect/Iterable'
28
+ *
29
+ * assert.deepStrictEqual(Array.from(makeBy(n => n * 2, { length: 5 })), [0, 2, 4, 6, 8])
30
+ *
31
+ * @category constructors
32
+ * @since 2.0.0
33
+ */
34
+ export const makeBy = <A>(f: (i: number) => A, options?: {
35
+ readonly length?: number
36
+ }): Iterable<A> => {
37
+ const max = options?.length !== undefined ? Math.max(1, Math.floor(options.length)) : Infinity
38
+ return {
39
+ [Symbol.iterator]() {
40
+ let i = 0
41
+ return {
42
+ next(): IteratorResult<A> {
43
+ if (i < max) {
44
+ return { value: f(i++), done: false }
45
+ }
46
+ return { done: true, value: undefined }
47
+ }
48
+ }
49
+ }
50
+ }
51
+ }
52
+
53
+ /**
54
+ * Return a `Iterable` containing a range of integers, including both endpoints.
55
+ *
56
+ * If `end` is omitted, the range will not have an upper bound.
57
+ *
58
+ * @example
59
+ * import { range } from 'effect/Iterable'
60
+ *
61
+ * assert.deepStrictEqual(Array.from(range(1, 3)), [1, 2, 3])
62
+ *
63
+ * @category constructors
64
+ * @since 2.0.0
65
+ */
66
+ export const range = (start: number, end?: number): Iterable<number> => {
67
+ if (end === undefined) {
68
+ return makeBy((i) => start + i)
69
+ }
70
+ return makeBy((i) => start + i, {
71
+ length: start <= end ? end - start + 1 : 1
72
+ })
73
+ }
74
+
75
+ /**
76
+ * Return a `Iterable` containing a value repeated the specified number of times.
77
+ *
78
+ * **Note**. `n` is normalized to an integer >= 1.
79
+ *
80
+ * @example
81
+ * import { replicate } from 'effect/Iterable'
82
+ *
83
+ * assert.deepStrictEqual(Array.from(replicate("a", 3)), ["a", "a", "a"])
84
+ *
85
+ * @category constructors
86
+ * @since 2.0.0
87
+ */
88
+ export const replicate: {
89
+ (n: number): <A>(a: A) => Iterable<A>
90
+ <A>(a: A, n: number): Iterable<A>
91
+ } = dual(2, <A>(a: A, n: number): Iterable<A> => makeBy(() => a, { length: n }))
92
+
93
+ /**
94
+ * Takes a record and returns an Iterable of tuples containing its keys and values.
95
+ *
96
+ * @param self - The record to transform.
97
+ *
98
+ * @example
99
+ * import { fromRecord } from "effect/Iterable"
100
+ *
101
+ * const x = { a: 1, b: 2, c: 3 }
102
+ * assert.deepStrictEqual(Array.from(fromRecord(x)), [["a", 1], ["b", 2], ["c", 3]])
103
+ *
104
+ * @category conversions
105
+ * @since 2.0.0
106
+ */
107
+ export const fromRecord = <K extends string, A>(self: Readonly<Record<K, A>>): Iterable<[K, A]> => ({
108
+ *[Symbol.iterator]() {
109
+ for (const key in self) {
110
+ if (Object.prototype.hasOwnProperty.call(self, key)) {
111
+ yield [key, self[key]]
112
+ }
113
+ }
114
+ }
115
+ })
116
+
117
+ /**
118
+ * Prepend an element to the front of an `Iterable`, creating a new `Iterable`.
119
+ *
120
+ * @category concatenating
121
+ * @since 2.0.0
122
+ */
123
+ export const prepend: {
124
+ <B>(head: B): <A>(self: Iterable<A>) => Iterable<A | B>
125
+ <A, B>(self: Iterable<A>, head: B): Iterable<A | B>
126
+ } = dual(2, <A, B>(self: Iterable<A>, head: B): Iterable<A | B> => flatten<A | B>([[head], self]))
127
+
128
+ /**
129
+ * Prepends the specified prefix iterable to the beginning of the specified iterable.
130
+ *
131
+ * @example
132
+ * import * as Iterable from "effect/Iterable"
133
+ *
134
+ * assert.deepStrictEqual(
135
+ * Array.from(Iterable.prependAll([1, 2], ["a", "b"])),
136
+ * ["a", "b", 1, 2]
137
+ * )
138
+ *
139
+ * @category concatenating
140
+ * @since 2.0.0
141
+ */
142
+ export const prependAll: {
143
+ <B>(that: Iterable<B>): <A>(self: Iterable<A>) => Iterable<A | B>
144
+ <A, B>(self: Iterable<A>, that: Iterable<B>): Iterable<A | B>
145
+ } = dual(
146
+ 2,
147
+ <A, B>(self: Iterable<A>, that: Iterable<B>): Iterable<A | B> => flatten<A | B>([that, self])
148
+ )
149
+
150
+ /**
151
+ * Append an element to the end of an `Iterable`, creating a new `Iterable`.
152
+ *
153
+ * @category concatenating
154
+ * @since 2.0.0
155
+ */
156
+ export const append: {
157
+ <B>(last: B): <A>(self: Iterable<A>) => Iterable<A | B>
158
+ <A, B>(self: Iterable<A>, last: B): Iterable<A | B>
159
+ } = dual(2, <A, B>(self: Iterable<A>, last: B): Iterable<A | B> => flatten<A | B>([self, [last]]))
160
+
161
+ /**
162
+ * Concatenates two iterables, combining their elements.
163
+ *
164
+ * @category concatenating
165
+ * @since 2.0.0
166
+ */
167
+ export const appendAll: {
168
+ <B>(that: Iterable<B>): <A>(self: Iterable<A>) => Iterable<A | B>
169
+ <A, B>(self: Iterable<A>, that: Iterable<B>): Iterable<A | B>
170
+ } = dual(
171
+ 2,
172
+ <A, B>(self: Iterable<A>, that: Iterable<B>): Iterable<A | B> => flatten<A | B>([self, that])
173
+ )
174
+
175
+ /**
176
+ * Reduce an `Iterable` from the left, keeping all intermediate results instead of only the final result.
177
+ *
178
+ * @category folding
179
+ * @since 2.0.0
180
+ */
181
+ export const scan: {
182
+ <B, A>(b: B, f: (b: B, a: A) => B): (self: Iterable<A>) => Iterable<B>
183
+ <A, B>(self: Iterable<A>, b: B, f: (b: B, a: A) => B): Iterable<B>
184
+ } = dual(3, <A, B>(self: Iterable<A>, b: B, f: (b: B, a: A) => B): Iterable<B> => ({
185
+ [Symbol.iterator]() {
186
+ let acc = b
187
+ let iterator: Iterator<A> | undefined
188
+ function next() {
189
+ if (iterator === undefined) {
190
+ iterator = self[Symbol.iterator]()
191
+ return { done: false, value: acc }
192
+ }
193
+ const result = iterator.next()
194
+ if (result.done) {
195
+ return result
196
+ }
197
+ acc = f(acc, result.value)
198
+ return { done: false, value: acc }
199
+ }
200
+ return { next }
201
+ }
202
+ }))
203
+
204
+ /**
205
+ * Determine if an `Iterable` is empty
206
+ *
207
+ * @example
208
+ * import { isEmpty } from "effect/Iterable"
209
+ *
210
+ * assert.deepStrictEqual(isEmpty([]), true);
211
+ * assert.deepStrictEqual(isEmpty([1, 2, 3]), false);
212
+ *
213
+ * @category guards
214
+ * @since 2.0.0
215
+ */
216
+ export const isEmpty = <A>(self: Iterable<A>): self is Iterable<never> => {
217
+ const iterator = self[Symbol.iterator]()
218
+ return iterator.next().done === true
219
+ }
220
+
221
+ /**
222
+ * Return the number of elements in a `Iterable`.
223
+ *
224
+ * @category getters
225
+ * @since 2.0.0
226
+ */
227
+ export const size = <A>(self: Iterable<A>): number => {
228
+ const iterator = self[Symbol.iterator]()
229
+ let count = 0
230
+ while (!iterator.next().done) {
231
+ count++
232
+ }
233
+ return count
234
+ }
235
+
236
+ /**
237
+ * Get the first element of a `Iterable`, or `None` if the `Iterable` is empty.
238
+ *
239
+ * @category getters
240
+ * @since 2.0.0
241
+ */
242
+ export const head = <A>(self: Iterable<A>): Option<A> => {
243
+ const iterator = self[Symbol.iterator]()
244
+ const result = iterator.next()
245
+ return result.done ? O.none() : O.some(result.value)
246
+ }
247
+
248
+ /**
249
+ * Keep only a max number of elements from the start of an `Iterable`, creating a new `Iterable`.
250
+ *
251
+ * **Note**. `n` is normalized to a non negative integer.
252
+ *
253
+ * @category getters
254
+ * @since 2.0.0
255
+ */
256
+ export const take: {
257
+ (n: number): <A>(self: Iterable<A>) => Iterable<A>
258
+ <A>(self: Iterable<A>, n: number): Iterable<A>
259
+ } = dual(2, <A>(self: Iterable<A>, n: number): Iterable<A> => ({
260
+ [Symbol.iterator]() {
261
+ let i = 0
262
+ const iterator = self[Symbol.iterator]()
263
+ return {
264
+ next() {
265
+ if (i < n) {
266
+ i++
267
+ return iterator.next()
268
+ }
269
+ return { done: true, value: undefined }
270
+ }
271
+ }
272
+ }
273
+ }))
274
+
275
+ /**
276
+ * Calculate the longest initial Iterable for which all element satisfy the specified predicate, creating a new `Iterable`.
277
+ *
278
+ * @category getters
279
+ * @since 2.0.0
280
+ */
281
+ export const takeWhile: {
282
+ <A, B extends A>(refinement: (a: NoInfer<A>, i: number) => a is B): (self: Iterable<A>) => Iterable<B>
283
+ <A>(predicate: (a: NoInfer<A>, i: number) => boolean): (self: Iterable<A>) => Iterable<A>
284
+ <A, B extends A>(self: Iterable<A>, refinement: (a: A, i: number) => a is B): Iterable<B>
285
+ <A>(self: Iterable<A>, predicate: (a: A, i: number) => boolean): Iterable<A>
286
+ } = dual(2, <A>(self: Iterable<A>, predicate: (a: A, i: number) => boolean): Iterable<A> => ({
287
+ [Symbol.iterator]() {
288
+ const iterator = self[Symbol.iterator]()
289
+ let i = 0
290
+ return {
291
+ next() {
292
+ const result = iterator.next()
293
+ if (result.done || !predicate(result.value, i++)) {
294
+ return { done: true, value: undefined }
295
+ }
296
+ return result
297
+ }
298
+ }
299
+ }
300
+ }))
301
+
302
+ /**
303
+ * Drop a max number of elements from the start of an `Iterable`
304
+ *
305
+ * **Note**. `n` is normalized to a non negative integer.
306
+ *
307
+ * @category getters
308
+ * @since 2.0.0
309
+ */
310
+ export const drop: {
311
+ (n: number): <A>(self: Iterable<A>) => Iterable<A>
312
+ <A>(self: Iterable<A>, n: number): Iterable<A>
313
+ } = dual(2, <A>(self: Iterable<A>, n: number): Iterable<A> => ({
314
+ [Symbol.iterator]() {
315
+ const iterator = self[Symbol.iterator]()
316
+ let i = 0
317
+ return {
318
+ next() {
319
+ while (i < n) {
320
+ const result = iterator.next()
321
+ if (result.done) {
322
+ return { done: true, value: undefined }
323
+ }
324
+ i++
325
+ }
326
+ return iterator.next()
327
+ }
328
+ }
329
+ }
330
+ }))
331
+
332
+ /**
333
+ * Returns the first element that satisfies the specified
334
+ * predicate, or `None` if no such element exists.
335
+ *
336
+ * @category elements
337
+ * @since 2.0.0
338
+ */
339
+ export const findFirst: {
340
+ <A, B>(f: (a: NoInfer<A>, i: number) => Option<B>): (self: Iterable<A>) => Option<B>
341
+ <A, B extends A>(refinement: (a: NoInfer<A>, i: number) => a is B): (self: Iterable<A>) => Option<B>
342
+ <A>(predicate: (a: NoInfer<A>, i: number) => boolean): (self: Iterable<A>) => Option<A>
343
+ <A, B>(self: Iterable<A>, f: (a: A, i: number) => Option<B>): Option<B>
344
+ <A, B extends A>(self: Iterable<A>, refinement: (a: A, i: number) => a is B): Option<B>
345
+ <A>(self: Iterable<A>, predicate: (a: A, i: number) => boolean): Option<A>
346
+ } = dual(
347
+ 2,
348
+ <A>(self: Iterable<A>, f: ((a: A, i: number) => boolean) | ((a: A, i: number) => Option<A>)): Option<A> => {
349
+ let i = 0
350
+ for (const a of self) {
351
+ const o = f(a, i)
352
+ if (isBoolean(o)) {
353
+ if (o) {
354
+ return O.some(a)
355
+ }
356
+ } else {
357
+ if (O.isSome(o)) {
358
+ return o
359
+ }
360
+ }
361
+ i++
362
+ }
363
+ return O.none()
364
+ }
365
+ )
366
+
367
+ /**
368
+ * Find the last element for which a predicate holds.
369
+ *
370
+ * @category elements
371
+ * @since 2.0.0
372
+ */
373
+ export const findLast: {
374
+ <A, B>(f: (a: NoInfer<A>, i: number) => Option<B>): (self: Iterable<A>) => Option<B>
375
+ <A, B extends A>(refinement: (a: NoInfer<A>, i: number) => a is B): (self: Iterable<A>) => Option<B>
376
+ <A>(predicate: (a: NoInfer<A>, i: number) => boolean): (self: Iterable<A>) => Option<A>
377
+ <A, B>(self: Iterable<A>, f: (a: A, i: number) => Option<B>): Option<B>
378
+ <A, B extends A>(self: Iterable<A>, refinement: (a: A, i: number) => a is B): Option<B>
379
+ <A>(self: Iterable<A>, predicate: (a: A, i: number) => boolean): Option<A>
380
+ } = dual(
381
+ 2,
382
+ <A>(self: Iterable<A>, f: ((a: A, i: number) => boolean) | ((a: A, i: number) => Option<A>)): Option<A> => {
383
+ let i = 0
384
+ let last: Option<A> = O.none()
385
+ for (const a of self) {
386
+ const o = f(a, i)
387
+ if (isBoolean(o)) {
388
+ if (o) {
389
+ last = O.some(a)
390
+ }
391
+ } else {
392
+ if (O.isSome(o)) {
393
+ last = o
394
+ }
395
+ }
396
+ i++
397
+ }
398
+ return last
399
+ }
400
+ )
401
+
402
+ /**
403
+ * Takes two `Iterable`s and returns an `Iterable` of corresponding pairs.
404
+ *
405
+ * @category zipping
406
+ * @since 2.0.0
407
+ */
408
+ export const zip: {
409
+ <B>(that: Iterable<B>): <A>(self: Iterable<A>) => Iterable<[A, B]>
410
+ <A, B>(self: Iterable<A>, that: Iterable<B>): Iterable<[A, B]>
411
+ } = dual(
412
+ 2,
413
+ <A, B>(self: Iterable<A>, that: Iterable<B>): Iterable<[A, B]> => zipWith(self, that, Tuple.make)
414
+ )
415
+
416
+ /**
417
+ * Apply a function to pairs of elements at the same index in two `Iterable`s, collecting the results. If one
418
+ * input `Iterable` is short, excess elements of the longer `Iterable` are discarded.
419
+ *
420
+ * @category zipping
421
+ * @since 2.0.0
422
+ */
423
+ export const zipWith: {
424
+ <B, A, C>(that: Iterable<B>, f: (a: A, b: B) => C): (self: Iterable<A>) => Iterable<C>
425
+ <A, B, C>(self: Iterable<A>, that: Iterable<B>, f: (a: A, b: B) => C): Iterable<C>
426
+ } = dual(3, <B, A, C>(self: Iterable<A>, that: Iterable<B>, f: (a: A, b: B) => C): Iterable<C> => ({
427
+ [Symbol.iterator]() {
428
+ const selfIterator = self[Symbol.iterator]()
429
+ const thatIterator = that[Symbol.iterator]()
430
+ return {
431
+ next() {
432
+ const selfResult = selfIterator.next()
433
+ const thatResult = thatIterator.next()
434
+ if (selfResult.done || thatResult.done) {
435
+ return { done: true, value: undefined }
436
+ }
437
+ return { done: false, value: f(selfResult.value, thatResult.value) }
438
+ }
439
+ }
440
+ }
441
+ }))
442
+
443
+ /**
444
+ * Places an element in between members of an `Iterable`.
445
+ * If the input is a non-empty array, the result is also a non-empty array.
446
+ *
447
+ * @since 2.0.0
448
+ */
449
+ export const intersperse: {
450
+ <B>(middle: B): <A>(self: Iterable<A>) => Iterable<A | B>
451
+ <A, B>(self: Iterable<A>, middle: B): Iterable<A | B>
452
+ } = dual(2, <A, B>(self: Iterable<A>, middle: B): Iterable<A | B> => ({
453
+ [Symbol.iterator]() {
454
+ const iterator = self[Symbol.iterator]()
455
+ let next = iterator.next()
456
+ let emitted = false
457
+ return {
458
+ next() {
459
+ if (next.done) {
460
+ return next
461
+ } else if (emitted) {
462
+ emitted = false
463
+ return { done: false, value: middle }
464
+ }
465
+ emitted = true
466
+ const result = next
467
+ next = iterator.next()
468
+ return result
469
+ }
470
+ }
471
+ }
472
+ }))
473
+
474
+ /**
475
+ * Returns a function that checks if an `Iterable` contains a given value using a provided `isEquivalent` function.
476
+ *
477
+ * @category elements
478
+ * @since 2.0.0
479
+ */
480
+ export const containsWith = <A>(isEquivalent: (self: A, that: A) => boolean): {
481
+ (a: A): (self: Iterable<A>) => boolean
482
+ (self: Iterable<A>, a: A): boolean
483
+ } =>
484
+ dual(2, (self: Iterable<A>, a: A): boolean => {
485
+ for (const i of self) {
486
+ if (isEquivalent(a, i)) {
487
+ return true
488
+ }
489
+ }
490
+ return false
491
+ })
492
+
493
+ const _equivalence = Equal.equivalence()
494
+
495
+ /**
496
+ * Returns a function that checks if a `Iterable` contains a given value using the default `Equivalence`.
497
+ *
498
+ * @category elements
499
+ * @since 2.0.0
500
+ */
501
+ export const contains: {
502
+ <A>(a: A): (self: Iterable<A>) => boolean
503
+ <A>(self: Iterable<A>, a: A): boolean
504
+ } = containsWith(_equivalence)
505
+
506
+ /**
507
+ * Splits an `Iterable` into length-`n` pieces. The last piece will be shorter if `n` does not evenly divide the length of
508
+ * the `Iterable`.
509
+ *
510
+ * @category splitting
511
+ * @since 2.0.0
512
+ */
513
+ export const chunksOf: {
514
+ (n: number): <A>(self: Iterable<A>) => Iterable<Array<A>>
515
+ <A>(self: Iterable<A>, n: number): Iterable<Array<A>>
516
+ } = dual(2, <A>(self: Iterable<A>, n: number): Iterable<Array<A>> => {
517
+ const safeN = Math.max(1, Math.floor(n))
518
+ return ({
519
+ [Symbol.iterator]() {
520
+ let iterator: Iterator<A> | undefined = self[Symbol.iterator]()
521
+ return {
522
+ next() {
523
+ if (iterator === undefined) {
524
+ return { done: true, value: undefined }
525
+ }
526
+
527
+ const chunk: Array<A> = []
528
+ for (let i = 0; i < safeN; i++) {
529
+ const result = iterator.next()
530
+ if (result.done) {
531
+ iterator = undefined
532
+ return chunk.length === 0 ? { done: true, value: undefined } : { done: false, value: chunk }
533
+ }
534
+ chunk.push(result.value)
535
+ }
536
+
537
+ return { done: false, value: chunk }
538
+ }
539
+ }
540
+ }
541
+ })
542
+ })
543
+
544
+ /**
545
+ * Group equal, consecutive elements of an `Iterable` into `NonEmptyArray`s using the provided `isEquivalent` function.
546
+ *
547
+ * @category grouping
548
+ * @since 2.0.0
549
+ */
550
+ export const groupWith: {
551
+ <A>(isEquivalent: (self: A, that: A) => boolean): (self: Iterable<A>) => Iterable<NonEmptyArray<A>>
552
+ <A>(self: Iterable<A>, isEquivalent: (self: A, that: A) => boolean): Iterable<NonEmptyArray<A>>
553
+ } = dual(
554
+ 2,
555
+ <A>(self: Iterable<A>, isEquivalent: (self: A, that: A) => boolean): Iterable<NonEmptyArray<A>> => ({
556
+ [Symbol.iterator]() {
557
+ const iterator = self[Symbol.iterator]()
558
+ let nextResult: IteratorResult<A> | undefined
559
+ return {
560
+ next() {
561
+ let result: IteratorResult<A>
562
+ if (nextResult !== undefined) {
563
+ if (nextResult.done) {
564
+ return { done: true, value: undefined }
565
+ }
566
+ result = nextResult
567
+ nextResult = undefined
568
+ } else {
569
+ result = iterator.next()
570
+ if (result.done) {
571
+ return { done: true, value: undefined }
572
+ }
573
+ }
574
+ const chunk: NonEmptyArray<A> = [result.value]
575
+ // eslint-disable-next-line no-constant-condition
576
+ while (true) {
577
+ const next = iterator.next()
578
+ if (next.done || !isEquivalent(result.value, next.value)) {
579
+ nextResult = next
580
+ return { done: false, value: chunk }
581
+ }
582
+ chunk.push(next.value)
583
+ }
584
+ }
585
+ }
586
+ }
587
+ })
588
+ )
589
+
590
+ /**
591
+ * Group equal, consecutive elements of an `Iterable` into `NonEmptyArray`s.
592
+ *
593
+ * @category grouping
594
+ * @since 2.0.0
595
+ */
596
+ export const group: <A>(self: Iterable<A>) => Iterable<NonEmptyArray<A>> = groupWith(
597
+ Equal.equivalence()
598
+ )
599
+
600
+ /**
601
+ * Splits an `Iterable` into sub-non-empty-arrays stored in an object, based on the result of calling a `string`-returning
602
+ * function on each element, and grouping the results according to values returned
603
+ *
604
+ * @category grouping
605
+ * @since 2.0.0
606
+ */
607
+ export const groupBy: {
608
+ <A, K extends string | symbol>(
609
+ f: (a: A) => K
610
+ ): (self: Iterable<A>) => Record<ReadonlyRecord.ReadonlyRecord.NonLiteralKey<K>, NonEmptyArray<A>>
611
+ <A, K extends string | symbol>(
612
+ self: Iterable<A>,
613
+ f: (a: A) => K
614
+ ): Record<ReadonlyRecord.ReadonlyRecord.NonLiteralKey<K>, NonEmptyArray<A>>
615
+ } = dual(2, <A, K extends string | symbol>(
616
+ self: Iterable<A>,
617
+ f: (a: A) => K
618
+ ): Record<ReadonlyRecord.ReadonlyRecord.NonLiteralKey<K>, NonEmptyArray<A>> => {
619
+ const out: Record<string | symbol, NonEmptyArray<A>> = {}
620
+ for (const a of self) {
621
+ const k = f(a)
622
+ if (Object.prototype.hasOwnProperty.call(out, k)) {
623
+ out[k].push(a)
624
+ } else {
625
+ out[k] = [a]
626
+ }
627
+ }
628
+ return out
629
+ })
630
+
631
+ const constEmpty: Iterable<never> = {
632
+ [Symbol.iterator]() {
633
+ return constEmptyIterator
634
+ }
635
+ }
636
+ const constEmptyIterator: Iterator<never> = {
637
+ next() {
638
+ return { done: true, value: undefined }
639
+ }
640
+ }
641
+
642
+ /**
643
+ * @category constructors
644
+ * @since 2.0.0
645
+ */
646
+ export const empty = <A = never>(): Iterable<A> => constEmpty
647
+
648
+ /**
649
+ * Constructs a new `Iterable<A>` from the specified value.
650
+ *
651
+ * @category constructors
652
+ * @since 2.0.0
653
+ */
654
+ export const of = <A>(a: A): Iterable<A> => [a]
655
+
656
+ /**
657
+ * @category mapping
658
+ * @since 2.0.0
659
+ */
660
+ export const map: {
661
+ <A, B>(
662
+ f: (a: NoInfer<A>, i: number) => B
663
+ ): (self: Iterable<A>) => Iterable<B>
664
+ <A, B>(self: Iterable<A>, f: (a: NoInfer<A>, i: number) => B): Iterable<B>
665
+ } = dual(2, <A, B>(self: Iterable<A>, f: (a: A, i: number) => B): Iterable<B> => ({
666
+ [Symbol.iterator]() {
667
+ const iterator = self[Symbol.iterator]()
668
+ let i = 0
669
+ return {
670
+ next() {
671
+ const result = iterator.next()
672
+ if (result.done) {
673
+ return { done: true, value: undefined }
674
+ }
675
+ return { done: false, value: f(result.value, i++) }
676
+ }
677
+ }
678
+ }
679
+ }))
680
+
681
+ /**
682
+ * Applies a function to each element in an Iterable and returns a new Iterable containing the concatenated mapped elements.
683
+ *
684
+ * @category sequencing
685
+ * @since 2.0.0
686
+ */
687
+ export const flatMap: {
688
+ <A, B>(
689
+ f: (a: NoInfer<A>, i: number) => Iterable<B>
690
+ ): (self: Iterable<A>) => Iterable<B>
691
+ <A, B>(self: Iterable<A>, f: (a: NoInfer<A>, i: number) => Iterable<B>): Iterable<B>
692
+ } = dual(
693
+ 2,
694
+ <A, B>(self: Iterable<A>, f: (a: A, i: number) => Iterable<B>): Iterable<B> => flatten(map(self, f))
695
+ )
696
+
697
+ /**
698
+ * Flattens an Iterable of Iterables into a single Iterable
699
+ *
700
+ * @category sequencing
701
+ * @since 2.0.0
702
+ */
703
+ export const flatten = <A>(self: Iterable<Iterable<A>>): Iterable<A> => ({
704
+ [Symbol.iterator]() {
705
+ const outerIterator = self[Symbol.iterator]()
706
+ let innerIterator: Iterator<A> | undefined
707
+ function next() {
708
+ if (innerIterator === undefined) {
709
+ const next = outerIterator.next()
710
+ if (next.done) {
711
+ return next
712
+ }
713
+ innerIterator = next.value[Symbol.iterator]()
714
+ }
715
+ const result = innerIterator.next()
716
+ if (result.done) {
717
+ innerIterator = undefined
718
+ return next()
719
+ }
720
+ return result
721
+ }
722
+ return { next }
723
+ }
724
+ })
725
+
726
+ /**
727
+ * @category filtering
728
+ * @since 2.0.0
729
+ */
730
+ export const filterMap: {
731
+ <A, B>(f: (a: A, i: number) => Option<B>): (self: Iterable<A>) => Iterable<B>
732
+ <A, B>(self: Iterable<A>, f: (a: A, i: number) => Option<B>): Iterable<B>
733
+ } = dual(
734
+ 2,
735
+ <A, B>(self: Iterable<A>, f: (a: A, i: number) => Option<B>): Iterable<B> => ({
736
+ [Symbol.iterator]() {
737
+ const iterator = self[Symbol.iterator]()
738
+ let i = 0
739
+ return {
740
+ next() {
741
+ let result = iterator.next()
742
+ while (!result.done) {
743
+ const b = f(result.value, i++)
744
+ if (O.isSome(b)) {
745
+ return { done: false, value: b.value }
746
+ }
747
+ result = iterator.next()
748
+ }
749
+ return { done: true, value: undefined }
750
+ }
751
+ }
752
+ }
753
+ })
754
+ )
755
+
756
+ /**
757
+ * Transforms all elements of the `Iterable` for as long as the specified function returns some value
758
+ *
759
+ * @category filtering
760
+ * @since 2.0.0
761
+ */
762
+ export const filterMapWhile: {
763
+ <A, B>(f: (a: A, i: number) => Option<B>): (self: Iterable<A>) => Iterable<B>
764
+ <A, B>(self: Iterable<A>, f: (a: A, i: number) => Option<B>): Iterable<B>
765
+ } = dual(2, <A, B>(self: Iterable<A>, f: (a: A, i: number) => Option<B>) => ({
766
+ [Symbol.iterator]() {
767
+ const iterator = self[Symbol.iterator]()
768
+ let i = 0
769
+ return {
770
+ next() {
771
+ const result = iterator.next()
772
+ if (result.done) {
773
+ return { done: true, value: undefined }
774
+ }
775
+ const b = f(result.value, i++)
776
+ if (O.isSome(b)) {
777
+ return { done: false, value: b.value }
778
+ }
779
+ return { done: true, value: undefined }
780
+ }
781
+ }
782
+ }
783
+ }))
784
+
785
+ /**
786
+ * Retrieves the `Some` values from an `Iterable` of `Option`s.
787
+ *
788
+ * @example
789
+ * import { getSomes } from "effect/Iterable"
790
+ * import { some, none } from "effect/Option"
791
+ *
792
+ * assert.deepStrictEqual(
793
+ * Array.from(getSomes([some(1), none(), some(2)])),
794
+ * [1, 2]
795
+ * )
796
+ *
797
+ * @category filtering
798
+ * @since 2.0.0
799
+ */
800
+ export const getSomes: <A>(self: Iterable<Option<A>>) => Iterable<A> = filterMap(identity)
801
+
802
+ /**
803
+ * Retrieves the `Left` values from an `Iterable` of `Either`s.
804
+ *
805
+ * @example
806
+ * import { getLefts } from "effect/Iterable"
807
+ * import { right, left } from "effect/Either"
808
+ *
809
+ * assert.deepStrictEqual(
810
+ * Array.from(getLefts([right(1), left("err"), right(2)])),
811
+ * ["err"]
812
+ * )
813
+ *
814
+ * @category filtering
815
+ * @since 2.0.0
816
+ */
817
+ export const getLefts = <R, L>(self: Iterable<Either<R, L>>): Iterable<L> => filterMap(self, E.getLeft)
818
+
819
+ /**
820
+ * Retrieves the `Right` values from an `Iterable` of `Either`s.
821
+ *
822
+ * @example
823
+ * import { getRights } from "effect/Iterable"
824
+ * import { right, left } from "effect/Either"
825
+ *
826
+ * assert.deepStrictEqual(
827
+ * Array.from(getRights([right(1), left("err"), right(2)])),
828
+ * [1, 2]
829
+ * )
830
+ *
831
+ * @category filtering
832
+ * @since 2.0.0
833
+ */
834
+ export const getRights = <R, L>(self: Iterable<Either<R, L>>): Iterable<R> => filterMap(self, E.getRight)
835
+
836
+ /**
837
+ * @category filtering
838
+ * @since 2.0.0
839
+ */
840
+ export const filter: {
841
+ <A, B extends A>(refinement: (a: NoInfer<A>, i: number) => a is B): (self: Iterable<A>) => Iterable<B>
842
+ <A>(predicate: (a: NoInfer<A>, i: number) => boolean): (self: Iterable<A>) => Iterable<A>
843
+ <A, B extends A>(self: Iterable<A>, refinement: (a: A, i: number) => a is B): Iterable<B>
844
+ <A>(self: Iterable<A>, predicate: (a: A, i: number) => boolean): Iterable<A>
845
+ } = dual(
846
+ 2,
847
+ <A>(self: Iterable<A>, predicate: (a: A, i: number) => boolean): Iterable<A> => ({
848
+ [Symbol.iterator]() {
849
+ const iterator = self[Symbol.iterator]()
850
+ let i = 0
851
+ return {
852
+ next() {
853
+ let result = iterator.next()
854
+ while (!result.done) {
855
+ if (predicate(result.value, i++)) {
856
+ return { done: false, value: result.value }
857
+ }
858
+ result = iterator.next()
859
+ }
860
+ return { done: true, value: undefined }
861
+ }
862
+ }
863
+ }
864
+ })
865
+ )
866
+
867
+ /**
868
+ * @category sequencing
869
+ * @since 2.0.0
870
+ */
871
+ export const flatMapNullable: {
872
+ <A, B>(f: (a: A) => B | null | undefined): (self: Iterable<A>) => Iterable<NonNullable<B>>
873
+ <A, B>(self: Iterable<A>, f: (a: A) => B | null | undefined): Iterable<NonNullable<B>>
874
+ } = dual(
875
+ 2,
876
+ <A, B>(self: Iterable<A>, f: (a: A) => B | null | undefined): Iterable<NonNullable<B>> =>
877
+ filterMap(self, (a) => {
878
+ const b = f(a)
879
+ return b == null ? O.none() : O.some(b)
880
+ })
881
+ )
882
+
883
+ /**
884
+ * Check if a predicate holds true for some `Iterable` element.
885
+ *
886
+ * @category elements
887
+ * @since 2.0.0
888
+ */
889
+ export const some: {
890
+ <A>(predicate: (a: A, i: number) => boolean): (self: Iterable<A>) => boolean
891
+ <A>(self: Iterable<A>, predicate: (a: A, i: number) => boolean): boolean
892
+ } = dual(
893
+ 2,
894
+ <A>(self: Iterable<A>, predicate: (a: A, i: number) => boolean): boolean => {
895
+ let i = 0
896
+ for (const a of self) {
897
+ if (predicate(a, i++)) {
898
+ return true
899
+ }
900
+ }
901
+ return false
902
+ }
903
+ )
904
+
905
+ /**
906
+ * @category constructors
907
+ * @since 2.0.0
908
+ */
909
+ export const unfold = <B, A>(b: B, f: (b: B) => Option<readonly [A, B]>): Iterable<A> => ({
910
+ [Symbol.iterator]() {
911
+ let next = b
912
+ return {
913
+ next() {
914
+ const o = f(next)
915
+ if (O.isNone(o)) {
916
+ return { done: true, value: undefined }
917
+ }
918
+ const [a, b] = o.value
919
+ next = b
920
+ return { done: false, value: a }
921
+ }
922
+ }
923
+ }
924
+ })
925
+
926
+ /**
927
+ * Iterate over the `Iterable` applying `f`.
928
+ *
929
+ * @since 2.0.0
930
+ */
931
+ export const forEach: {
932
+ <A>(f: (a: A, i: number) => void): (self: Iterable<A>) => void
933
+ <A>(self: Iterable<A>, f: (a: A, i: number) => void): void
934
+ } = dual(2, <A>(self: Iterable<A>, f: (a: A, i: number) => void): void => {
935
+ let i = 0
936
+ for (const a of self) {
937
+ f(a, i++)
938
+ }
939
+ })
940
+
941
+ /**
942
+ * Deduplicates adjacent elements that are identical using the provided `isEquivalent` function.
943
+ *
944
+ * @since 2.0.0
945
+ */
946
+ export const dedupeAdjacentWith: {
947
+ <A>(isEquivalent: (self: A, that: A) => boolean): (self: Iterable<A>) => Iterable<A>
948
+ <A>(self: Iterable<A>, isEquivalent: (self: A, that: A) => boolean): Iterable<A>
949
+ } = dual(2, <A>(self: Iterable<A>, isEquivalent: (self: A, that: A) => boolean): Iterable<A> => ({
950
+ [Symbol.iterator]() {
951
+ const iterator = self[Symbol.iterator]()
952
+ let first = true
953
+ let last: A
954
+ function next(): IteratorResult<A> {
955
+ const result = iterator.next()
956
+ if (result.done) {
957
+ return { done: true, value: undefined }
958
+ }
959
+ if (first) {
960
+ first = false
961
+ last = result.value
962
+ return result
963
+ }
964
+ const current = result.value
965
+ if (isEquivalent(last, current)) {
966
+ return next()
967
+ }
968
+ last = current
969
+ return result
970
+ }
971
+ return { next }
972
+ }
973
+ }))
974
+
975
+ /**
976
+ * Deduplicates adjacent elements that are identical.
977
+ *
978
+ * @since 2.0.0
979
+ */
980
+ export const dedupeAdjacent: <A>(self: Iterable<A>) => Iterable<A> = dedupeAdjacentWith(Equal.equivalence())
981
+
982
+ /**
983
+ * Zips this Iterable crosswise with the specified Iterable using the specified combiner.
984
+ *
985
+ * @since 2.0.0
986
+ * @category elements
987
+ */
988
+ export const cartesianWith: {
989
+ <A, B, C>(that: Iterable<B>, f: (a: A, b: B) => C): (self: Iterable<A>) => Iterable<C>
990
+ <A, B, C>(self: Iterable<A>, that: Iterable<B>, f: (a: A, b: B) => C): Iterable<C>
991
+ } = dual(
992
+ 3,
993
+ <A, B, C>(self: Iterable<A>, that: Iterable<B>, f: (a: A, b: B) => C): Iterable<C> =>
994
+ flatMap(self, (a) => map(that, (b) => f(a, b)))
995
+ )
996
+
997
+ /**
998
+ * Zips this Iterable crosswise with the specified Iterable.
999
+ *
1000
+ * @since 2.0.0
1001
+ * @category elements
1002
+ */
1003
+ export const cartesian: {
1004
+ <B>(that: Iterable<B>): <A>(self: Iterable<A>) => Iterable<[A, B]>
1005
+ <A, B>(self: Iterable<A>, that: Iterable<B>): Iterable<[A, B]>
1006
+ } = dual(
1007
+ 2,
1008
+ <A, B>(self: Iterable<A>, that: Iterable<B>): Iterable<[A, B]> => cartesianWith(self, that, (a, b) => [a, b])
1009
+ )