effect
Version:
The missing standard library for TypeScript, for writing production-grade software.
1,775 lines (1,723 loc) • 192 kB
text/typescript
/**
* This module provides utility functions for working with arrays in TypeScript.
*
* @since 2.0.0
*/
import type { Either } from "./Either.js"
import * as E from "./Either.js"
import * as Equal from "./Equal.js"
import * as Equivalence from "./Equivalence.js"
import type { LazyArg } from "./Function.js"
import { dual, identity } from "./Function.js"
import type { TypeLambda } from "./HKT.js"
import * as readonlyArray from "./internal/array.js"
import * as doNotation from "./internal/doNotation.js"
import * as EffectIterable from "./Iterable.js"
import type { Option } from "./Option.js"
import * as O from "./Option.js"
import * as Order from "./Order.js"
import type { Predicate, Refinement } from "./Predicate.js"
import { isBoolean } from "./Predicate.js"
import * as Record from "./Record.js"
import * as Tuple from "./Tuple.js"
import type { NoInfer } from "./Types.js"
/**
* @category type lambdas
* @since 2.0.0
*/
export interface ReadonlyArrayTypeLambda extends TypeLambda {
readonly type: ReadonlyArray<this["Target"]>
}
/**
* @category models
* @since 2.0.0
*/
export type NonEmptyReadonlyArray<A> = readonly [A, ...Array<A>]
/**
* @category models
* @since 2.0.0
*/
export type NonEmptyArray<A> = [A, ...Array<A>]
/**
* Builds a `NonEmptyArray` from an non-empty collection of elements.
*
* @example
* ```ts
* import { Array } from "effect"
*
* const result = Array.make(1, 2, 3)
* assert.deepStrictEqual(result, [1, 2, 3])
* ```
*
* @category constructors
* @since 2.0.0
*/
export const make = <Elements extends NonEmptyArray<any>>(
...elements: Elements
): NonEmptyArray<Elements[number]> => elements
/**
* Creates a new `Array` of the specified length.
*
* @example
* ```ts
* import { Array } from "effect"
*
* const result = Array.allocate<number>(3)
* assert.deepStrictEqual(result.length, 3)
* ```
*
* @category constructors
* @since 2.0.0
*/
export const allocate = <A = never>(n: number): Array<A | undefined> => new Array(n)
/**
* Return a `NonEmptyArray` of length `n` with element `i` initialized with `f(i)`.
*
* **Note**. `n` is normalized to an integer >= 1.
*
* @example
* ```ts
* import { makeBy } from "effect/Array"
*
* assert.deepStrictEqual(makeBy(5, n => n * 2), [0, 2, 4, 6, 8])
* ```
*
* @category constructors
* @since 2.0.0
*/
export const makeBy: {
/**
* Return a `NonEmptyArray` of length `n` with element `i` initialized with `f(i)`.
*
* **Note**. `n` is normalized to an integer >= 1.
*
* @example
* ```ts
* import { makeBy } from "effect/Array"
*
* assert.deepStrictEqual(makeBy(5, n => n * 2), [0, 2, 4, 6, 8])
* ```
*
* @category constructors
* @since 2.0.0
*/
<A>(f: (i: number) => A): (n: number) => NonEmptyArray<A>
/**
* Return a `NonEmptyArray` of length `n` with element `i` initialized with `f(i)`.
*
* **Note**. `n` is normalized to an integer >= 1.
*
* @example
* ```ts
* import { makeBy } from "effect/Array"
*
* assert.deepStrictEqual(makeBy(5, n => n * 2), [0, 2, 4, 6, 8])
* ```
*
* @category constructors
* @since 2.0.0
*/
<A>(n: number, f: (i: number) => A): NonEmptyArray<A>
} = dual(2, <A>(n: number, f: (i: number) => A) => {
const max = Math.max(1, Math.floor(n))
const out = new Array(max)
for (let i = 0; i < max; i++) {
out[i] = f(i)
}
return out as NonEmptyArray<A>
})
/**
* Return a `NonEmptyArray` containing a range of integers, including both endpoints.
*
* @example
* ```ts
* import { range } from "effect/Array"
*
* assert.deepStrictEqual(range(1, 3), [1, 2, 3])
* ```
*
* @category constructors
* @since 2.0.0
*/
export const range = (start: number, end: number): NonEmptyArray<number> =>
start <= end ? makeBy(end - start + 1, (i) => start + i) : [start]
/**
* Return a `NonEmptyArray` containing a value repeated the specified number of times.
*
* **Note**. `n` is normalized to an integer >= 1.
*
* @example
* ```ts
* import { Array } from "effect"
*
* assert.deepStrictEqual(Array.replicate("a", 3), ["a", "a", "a"])
* ```
*
* @category constructors
* @since 2.0.0
*/
export const replicate: {
/**
* Return a `NonEmptyArray` containing a value repeated the specified number of times.
*
* **Note**. `n` is normalized to an integer >= 1.
*
* @example
* ```ts
* import { Array } from "effect"
*
* assert.deepStrictEqual(Array.replicate("a", 3), ["a", "a", "a"])
* ```
*
* @category constructors
* @since 2.0.0
*/
(n: number): <A>(a: A) => NonEmptyArray<A>
/**
* Return a `NonEmptyArray` containing a value repeated the specified number of times.
*
* **Note**. `n` is normalized to an integer >= 1.
*
* @example
* ```ts
* import { Array } from "effect"
*
* assert.deepStrictEqual(Array.replicate("a", 3), ["a", "a", "a"])
* ```
*
* @category constructors
* @since 2.0.0
*/
<A>(a: A, n: number): NonEmptyArray<A>
} = dual(2, <A>(a: A, n: number): NonEmptyArray<A> => makeBy(n, () => a))
/**
* Creates a new `Array` from an iterable collection of values.
* If the input is already an array, it returns the input as-is.
* Otherwise, it converts the iterable collection to an array.
*
* @example
* ```ts
* import { Array } from "effect"
*
* const set = new Set([1, 2, 3])
* const result = Array.fromIterable(set)
* assert.deepStrictEqual(result, [1, 2, 3])
* ```
*
* @category constructors
* @since 2.0.0
*/
export const fromIterable = <A>(collection: Iterable<A>): Array<A> =>
Array.isArray(collection) ? collection : Array.from(collection)
/**
* Creates a new `Array` from a value that might not be an iterable.
*
* @example
* ```ts
* import { Array } from "effect"
*
* assert.deepStrictEqual(Array.ensure("a"), ["a"])
* assert.deepStrictEqual(Array.ensure(["a"]), ["a"])
* assert.deepStrictEqual(Array.ensure(["a", "b", "c"]), ["a", "b", "c"])
* ```
*
* @category constructors
* @since 3.3.0
*/
export const ensure = <A>(self: ReadonlyArray<A> | A): Array<A> => Array.isArray(self) ? self : [self as A]
/**
* Takes a record and returns an array of tuples containing its keys and values.
*
* @param self - The record to transform.
*
* @example
* ```ts
* import { Array } from "effect"
*
* const x = { a: 1, b: 2, c: 3 }
* assert.deepStrictEqual(Array.fromRecord(x), [["a", 1], ["b", 2], ["c", 3]])
* ```
*
* @category conversions
* @since 2.0.0
*/
export const fromRecord: <K extends string, A>(self: Readonly<Record<K, A>>) => Array<[K, A]> = Record.toEntries
/**
* Converts an `Option` to an array.
*
* @example
* ```ts
* import { Array, Option } from "effect"
*
* assert.deepStrictEqual(Array.fromOption(Option.some(1)), [1])
* assert.deepStrictEqual(Array.fromOption(Option.none()), [])
* ```
*
* @category conversions
* @since 2.0.0
*/
export const fromOption: <A>(self: Option<A>) => Array<A> = O.toArray
/**
* Matches the elements of an array, applying functions to cases of empty and non-empty arrays.
*
* @example
* ```ts
* import { Array } from "effect"
*
* const match = Array.match({
* onEmpty: () => "empty",
* onNonEmpty: ([head, ...tail]) => `head: ${head}, tail: ${tail.length}`
* })
* assert.deepStrictEqual(match([]), "empty")
* assert.deepStrictEqual(match([1, 2, 3]), "head: 1, tail: 2")
* ```
*
* @category pattern matching
* @since 2.0.0
*/
export const match: {
/**
* Matches the elements of an array, applying functions to cases of empty and non-empty arrays.
*
* @example
* ```ts
* import { Array } from "effect"
*
* const match = Array.match({
* onEmpty: () => "empty",
* onNonEmpty: ([head, ...tail]) => `head: ${head}, tail: ${tail.length}`
* })
* assert.deepStrictEqual(match([]), "empty")
* assert.deepStrictEqual(match([1, 2, 3]), "head: 1, tail: 2")
* ```
*
* @category pattern matching
* @since 2.0.0
*/
<B, A, C = B>(
options: {
readonly onEmpty: LazyArg<B>
readonly onNonEmpty: (self: NonEmptyReadonlyArray<A>) => C
}
): (self: ReadonlyArray<A>) => B | C
/**
* Matches the elements of an array, applying functions to cases of empty and non-empty arrays.
*
* @example
* ```ts
* import { Array } from "effect"
*
* const match = Array.match({
* onEmpty: () => "empty",
* onNonEmpty: ([head, ...tail]) => `head: ${head}, tail: ${tail.length}`
* })
* assert.deepStrictEqual(match([]), "empty")
* assert.deepStrictEqual(match([1, 2, 3]), "head: 1, tail: 2")
* ```
*
* @category pattern matching
* @since 2.0.0
*/
<A, B, C = B>(
self: ReadonlyArray<A>,
options: {
readonly onEmpty: LazyArg<B>
readonly onNonEmpty: (self: NonEmptyReadonlyArray<A>) => C
}
): B | C
} = dual(2, <A, B, C = B>(
self: ReadonlyArray<A>,
{ onEmpty, onNonEmpty }: {
readonly onEmpty: LazyArg<B>
readonly onNonEmpty: (self: NonEmptyReadonlyArray<A>) => C
}
): B | C => isNonEmptyReadonlyArray(self) ? onNonEmpty(self) : onEmpty())
/**
* Matches the elements of an array from the left, applying functions to cases of empty and non-empty arrays.
*
* @example
* ```ts
* import { Array } from "effect"
*
* const matchLeft = Array.matchLeft({
* onEmpty: () => "empty",
* onNonEmpty: (head, tail) => `head: ${head}, tail: ${tail.length}`
* })
* assert.deepStrictEqual(matchLeft([]), "empty")
* assert.deepStrictEqual(matchLeft([1, 2, 3]), "head: 1, tail: 2")
* ```
*
* @category pattern matching
* @since 2.0.0
*/
export const matchLeft: {
/**
* Matches the elements of an array from the left, applying functions to cases of empty and non-empty arrays.
*
* @example
* ```ts
* import { Array } from "effect"
*
* const matchLeft = Array.matchLeft({
* onEmpty: () => "empty",
* onNonEmpty: (head, tail) => `head: ${head}, tail: ${tail.length}`
* })
* assert.deepStrictEqual(matchLeft([]), "empty")
* assert.deepStrictEqual(matchLeft([1, 2, 3]), "head: 1, tail: 2")
* ```
*
* @category pattern matching
* @since 2.0.0
*/
<B, A, C = B>(
options: {
readonly onEmpty: LazyArg<B>
readonly onNonEmpty: (head: A, tail: Array<A>) => C
}
): (self: ReadonlyArray<A>) => B | C
/**
* Matches the elements of an array from the left, applying functions to cases of empty and non-empty arrays.
*
* @example
* ```ts
* import { Array } from "effect"
*
* const matchLeft = Array.matchLeft({
* onEmpty: () => "empty",
* onNonEmpty: (head, tail) => `head: ${head}, tail: ${tail.length}`
* })
* assert.deepStrictEqual(matchLeft([]), "empty")
* assert.deepStrictEqual(matchLeft([1, 2, 3]), "head: 1, tail: 2")
* ```
*
* @category pattern matching
* @since 2.0.0
*/
<A, B, C = B>(
self: ReadonlyArray<A>,
options: {
readonly onEmpty: LazyArg<B>
readonly onNonEmpty: (head: A, tail: Array<A>) => C
}
): B | C
} = dual(2, <A, B, C = B>(
self: ReadonlyArray<A>,
{ onEmpty, onNonEmpty }: {
readonly onEmpty: LazyArg<B>
readonly onNonEmpty: (head: A, tail: Array<A>) => C
}
): B | C => isNonEmptyReadonlyArray(self) ? onNonEmpty(headNonEmpty(self), tailNonEmpty(self)) : onEmpty())
/**
* Matches the elements of an array from the right, applying functions to cases of empty and non-empty arrays.
*
* @example
* ```ts
* import { Array } from "effect"
*
* const matchRight = Array.matchRight({
* onEmpty: () => "empty",
* onNonEmpty: (init, last) => `init: ${init.length}, last: ${last}`
* })
* assert.deepStrictEqual(matchRight([]), "empty")
* assert.deepStrictEqual(matchRight([1, 2, 3]), "init: 2, last: 3")
* ```
*
* @category pattern matching
* @since 2.0.0
*/
export const matchRight: {
/**
* Matches the elements of an array from the right, applying functions to cases of empty and non-empty arrays.
*
* @example
* ```ts
* import { Array } from "effect"
*
* const matchRight = Array.matchRight({
* onEmpty: () => "empty",
* onNonEmpty: (init, last) => `init: ${init.length}, last: ${last}`
* })
* assert.deepStrictEqual(matchRight([]), "empty")
* assert.deepStrictEqual(matchRight([1, 2, 3]), "init: 2, last: 3")
* ```
*
* @category pattern matching
* @since 2.0.0
*/
<B, A, C = B>(
options: {
readonly onEmpty: LazyArg<B>
readonly onNonEmpty: (init: Array<A>, last: A) => C
}
): (self: ReadonlyArray<A>) => B | C
/**
* Matches the elements of an array from the right, applying functions to cases of empty and non-empty arrays.
*
* @example
* ```ts
* import { Array } from "effect"
*
* const matchRight = Array.matchRight({
* onEmpty: () => "empty",
* onNonEmpty: (init, last) => `init: ${init.length}, last: ${last}`
* })
* assert.deepStrictEqual(matchRight([]), "empty")
* assert.deepStrictEqual(matchRight([1, 2, 3]), "init: 2, last: 3")
* ```
*
* @category pattern matching
* @since 2.0.0
*/
<A, B, C = B>(
self: ReadonlyArray<A>,
options: {
readonly onEmpty: LazyArg<B>
readonly onNonEmpty: (init: Array<A>, last: A) => C
}
): B | C
} = dual(2, <A, B, C = B>(
self: ReadonlyArray<A>,
{ onEmpty, onNonEmpty }: {
readonly onEmpty: LazyArg<B>
readonly onNonEmpty: (init: Array<A>, last: A) => C
}
): B | C =>
isNonEmptyReadonlyArray(self) ?
onNonEmpty(initNonEmpty(self), lastNonEmpty(self)) :
onEmpty())
/**
* Prepend an element to the front of an `Iterable`, creating a new `NonEmptyArray`.
*
* @example
* ```ts
* import { Array } from "effect"
*
* const original = [2, 3, 4];
* const result = Array.prepend(original, 1);
* assert.deepStrictEqual(result, [1, 2, 3, 4]);
* ```
*
* @category concatenating
* @since 2.0.0
*/
export const prepend: {
/**
* Prepend an element to the front of an `Iterable`, creating a new `NonEmptyArray`.
*
* @example
* ```ts
* import { Array } from "effect"
*
* const original = [2, 3, 4];
* const result = Array.prepend(original, 1);
* assert.deepStrictEqual(result, [1, 2, 3, 4]);
* ```
*
* @category concatenating
* @since 2.0.0
*/
<B>(head: B): <A>(self: Iterable<A>) => NonEmptyArray<A | B>
/**
* Prepend an element to the front of an `Iterable`, creating a new `NonEmptyArray`.
*
* @example
* ```ts
* import { Array } from "effect"
*
* const original = [2, 3, 4];
* const result = Array.prepend(original, 1);
* assert.deepStrictEqual(result, [1, 2, 3, 4]);
* ```
*
* @category concatenating
* @since 2.0.0
*/
<A, B>(self: Iterable<A>, head: B): NonEmptyArray<A | B>
} = dual(2, <A, B>(self: Iterable<A>, head: B): NonEmptyArray<A | B> => [head, ...self])
/**
* Prepends the specified prefix array (or iterable) to the beginning of the specified array (or iterable).
* If either array is non-empty, the result is also a non-empty array.
*
* @example
* ```ts
* import { Array } from "effect"
*
* const prefix = [0, 1];
* const array = [2, 3];
* const result = Array.prependAll(array, prefix);
* assert.deepStrictEqual(result, [0, 1, 2, 3]);
* ```
*
* @category concatenating
* @since 2.0.0
*/
export const prependAll: {
/**
* Prepends the specified prefix array (or iterable) to the beginning of the specified array (or iterable).
* If either array is non-empty, the result is also a non-empty array.
*
* @example
* ```ts
* import { Array } from "effect"
*
* const prefix = [0, 1];
* const array = [2, 3];
* const result = Array.prependAll(array, prefix);
* assert.deepStrictEqual(result, [0, 1, 2, 3]);
* ```
*
* @category concatenating
* @since 2.0.0
*/
<S extends Iterable<any>, T extends Iterable<any>>(that: T): (self: S) => ReadonlyArray.OrNonEmpty<S, T, ReadonlyArray.Infer<S> | ReadonlyArray.Infer<T>>
/**
* Prepends the specified prefix array (or iterable) to the beginning of the specified array (or iterable).
* If either array is non-empty, the result is also a non-empty array.
*
* @example
* ```ts
* import { Array } from "effect"
*
* const prefix = [0, 1];
* const array = [2, 3];
* const result = Array.prependAll(array, prefix);
* assert.deepStrictEqual(result, [0, 1, 2, 3]);
* ```
*
* @category concatenating
* @since 2.0.0
*/
<A, B>(self: Iterable<A>, that: NonEmptyReadonlyArray<B>): NonEmptyArray<A | B>
/**
* Prepends the specified prefix array (or iterable) to the beginning of the specified array (or iterable).
* If either array is non-empty, the result is also a non-empty array.
*
* @example
* ```ts
* import { Array } from "effect"
*
* const prefix = [0, 1];
* const array = [2, 3];
* const result = Array.prependAll(array, prefix);
* assert.deepStrictEqual(result, [0, 1, 2, 3]);
* ```
*
* @category concatenating
* @since 2.0.0
*/
<A, B>(self: NonEmptyReadonlyArray<A>, that: Iterable<B>): NonEmptyArray<A | B>
/**
* Prepends the specified prefix array (or iterable) to the beginning of the specified array (or iterable).
* If either array is non-empty, the result is also a non-empty array.
*
* @example
* ```ts
* import { Array } from "effect"
*
* const prefix = [0, 1];
* const array = [2, 3];
* const result = Array.prependAll(array, prefix);
* assert.deepStrictEqual(result, [0, 1, 2, 3]);
* ```
*
* @category concatenating
* @since 2.0.0
*/
<A, B>(self: Iterable<A>, that: Iterable<B>): Array<A | B>
} = dual(
2,
<A>(self: Iterable<A>, that: Iterable<A>): Array<A> => fromIterable(that).concat(fromIterable(self))
)
/**
* Append an element to the end of an `Iterable`, creating a new `NonEmptyArray`.
*
* @example
* ```ts
* import { Array } from "effect"
*
* const original = [1, 2, 3];
* const result = Array.append(original, 4);
* assert.deepStrictEqual(result, [1, 2, 3, 4]);
* ```
*
* @category concatenating
* @since 2.0.0
*/
export const append: {
/**
* Append an element to the end of an `Iterable`, creating a new `NonEmptyArray`.
*
* @example
* ```ts
* import { Array } from "effect"
*
* const original = [1, 2, 3];
* const result = Array.append(original, 4);
* assert.deepStrictEqual(result, [1, 2, 3, 4]);
* ```
*
* @category concatenating
* @since 2.0.0
*/
<B>(last: B): <A>(self: Iterable<A>) => NonEmptyArray<A | B>
/**
* Append an element to the end of an `Iterable`, creating a new `NonEmptyArray`.
*
* @example
* ```ts
* import { Array } from "effect"
*
* const original = [1, 2, 3];
* const result = Array.append(original, 4);
* assert.deepStrictEqual(result, [1, 2, 3, 4]);
* ```
*
* @category concatenating
* @since 2.0.0
*/
<A, B>(self: Iterable<A>, last: B): NonEmptyArray<A | B>
} = dual(2, <A, B>(self: Iterable<A>, last: B): Array<A | B> => [...self, last])
/**
* Concatenates two arrays (or iterables), combining their elements.
* If either array is non-empty, the result is also a non-empty array.
*
* @category concatenating
* @since 2.0.0
*/
export const appendAll: {
/**
* Concatenates two arrays (or iterables), combining their elements.
* If either array is non-empty, the result is also a non-empty array.
*
* @category concatenating
* @since 2.0.0
*/
<S extends Iterable<any>, T extends Iterable<any>>(that: T): (self: S) => ReadonlyArray.OrNonEmpty<S, T, ReadonlyArray.Infer<S> | ReadonlyArray.Infer<T>>
/**
* Concatenates two arrays (or iterables), combining their elements.
* If either array is non-empty, the result is also a non-empty array.
*
* @category concatenating
* @since 2.0.0
*/
<A, B>(self: Iterable<A>, that: NonEmptyReadonlyArray<B>): NonEmptyArray<A | B>
/**
* Concatenates two arrays (or iterables), combining their elements.
* If either array is non-empty, the result is also a non-empty array.
*
* @category concatenating
* @since 2.0.0
*/
<A, B>(self: NonEmptyReadonlyArray<A>, that: Iterable<B>): NonEmptyArray<A | B>
/**
* Concatenates two arrays (or iterables), combining their elements.
* If either array is non-empty, the result is also a non-empty array.
*
* @category concatenating
* @since 2.0.0
*/
<A, B>(self: Iterable<A>, that: Iterable<B>): Array<A | B>
} = dual(
2,
<A>(self: Iterable<A>, that: Iterable<A>): Array<A> => fromIterable(self).concat(fromIterable(that))
)
/**
* Accumulates values from an `Iterable` starting from the left, storing
* each intermediate result in an array. Useful for tracking the progression of
* a value through a series of transformations.
*
* @example
* ```ts
* import { Array } from "effect";
*
* const numbers = [1, 2, 3, 4]
* const result = Array.scan(numbers, 0, (acc, value) => acc + value)
* assert.deepStrictEqual(result, [0, 1, 3, 6, 10])
*
* // Explanation:
* // This function starts with the initial value (0 in this case)
* // and adds each element of the array to this accumulator one by one,
* // keeping track of the cumulative sum after each addition.
* // Each of these sums is captured in the resulting array.
* ```
*
* @category folding
* @since 2.0.0
*/
export const scan: {
/**
* Accumulates values from an `Iterable` starting from the left, storing
* each intermediate result in an array. Useful for tracking the progression of
* a value through a series of transformations.
*
* @example
* ```ts
* import { Array } from "effect";
*
* const numbers = [1, 2, 3, 4]
* const result = Array.scan(numbers, 0, (acc, value) => acc + value)
* assert.deepStrictEqual(result, [0, 1, 3, 6, 10])
*
* // Explanation:
* // This function starts with the initial value (0 in this case)
* // and adds each element of the array to this accumulator one by one,
* // keeping track of the cumulative sum after each addition.
* // Each of these sums is captured in the resulting array.
* ```
*
* @category folding
* @since 2.0.0
*/
<B, A>(b: B, f: (b: B, a: A) => B): (self: Iterable<A>) => NonEmptyArray<B>
/**
* Accumulates values from an `Iterable` starting from the left, storing
* each intermediate result in an array. Useful for tracking the progression of
* a value through a series of transformations.
*
* @example
* ```ts
* import { Array } from "effect";
*
* const numbers = [1, 2, 3, 4]
* const result = Array.scan(numbers, 0, (acc, value) => acc + value)
* assert.deepStrictEqual(result, [0, 1, 3, 6, 10])
*
* // Explanation:
* // This function starts with the initial value (0 in this case)
* // and adds each element of the array to this accumulator one by one,
* // keeping track of the cumulative sum after each addition.
* // Each of these sums is captured in the resulting array.
* ```
*
* @category folding
* @since 2.0.0
*/
<A, B>(self: Iterable<A>, b: B, f: (b: B, a: A) => B): NonEmptyArray<B>
} = dual(3, <A, B>(self: Iterable<A>, b: B, f: (b: B, a: A) => B): NonEmptyArray<B> => {
const out: NonEmptyArray<B> = [b]
let i = 0
for (const a of self) {
out[i + 1] = f(out[i], a)
i++
}
return out
})
/**
* Accumulates values from an `Iterable` starting from the right, storing
* each intermediate result in an array. Useful for tracking the progression of
* a value through a series of transformations.
*
* @example
* ```ts
* import { Array } from "effect";
*
* const numbers = [1, 2, 3, 4]
* const result = Array.scanRight(numbers, 0, (acc, value) => acc + value)
* assert.deepStrictEqual(result, [10, 9, 7, 4, 0])
* ```
*
* @category folding
* @since 2.0.0
*/
export const scanRight: {
/**
* Accumulates values from an `Iterable` starting from the right, storing
* each intermediate result in an array. Useful for tracking the progression of
* a value through a series of transformations.
*
* @example
* ```ts
* import { Array } from "effect";
*
* const numbers = [1, 2, 3, 4]
* const result = Array.scanRight(numbers, 0, (acc, value) => acc + value)
* assert.deepStrictEqual(result, [10, 9, 7, 4, 0])
* ```
*
* @category folding
* @since 2.0.0
*/
<B, A>(b: B, f: (b: B, a: A) => B): (self: Iterable<A>) => NonEmptyArray<B>
/**
* Accumulates values from an `Iterable` starting from the right, storing
* each intermediate result in an array. Useful for tracking the progression of
* a value through a series of transformations.
*
* @example
* ```ts
* import { Array } from "effect";
*
* const numbers = [1, 2, 3, 4]
* const result = Array.scanRight(numbers, 0, (acc, value) => acc + value)
* assert.deepStrictEqual(result, [10, 9, 7, 4, 0])
* ```
*
* @category folding
* @since 2.0.0
*/
<A, B>(self: Iterable<A>, b: B, f: (b: B, a: A) => B): NonEmptyArray<B>
} = dual(3, <A, B>(self: Iterable<A>, b: B, f: (b: B, a: A) => B): NonEmptyArray<B> => {
const input = fromIterable(self)
const out: NonEmptyArray<B> = new Array(input.length + 1) as any
out[input.length] = b
for (let i = input.length - 1; i >= 0; i--) {
out[i] = f(out[i + 1], input[i])
}
return out
})
/**
* Determine if `unknown` is an Array.
*
* @param self - The value to check.
*
* @example
* ```ts
* import { isArray } from "effect/Array"
*
* assert.deepStrictEqual(isArray(null), false);
* assert.deepStrictEqual(isArray([1, 2, 3]), true);
* ```
*
* @category guards
* @since 2.0.0
*/
export const isArray: {
/**
* Determine if `unknown` is an Array.
*
* @param self - The value to check.
*
* @example
* ```ts
* import { isArray } from "effect/Array"
*
* assert.deepStrictEqual(isArray(null), false);
* assert.deepStrictEqual(isArray([1, 2, 3]), true);
* ```
*
* @category guards
* @since 2.0.0
*/
(self: unknown): self is Array<unknown>
/**
* Determine if `unknown` is an Array.
*
* @param self - The value to check.
*
* @example
* ```ts
* import { isArray } from "effect/Array"
*
* assert.deepStrictEqual(isArray(null), false);
* assert.deepStrictEqual(isArray([1, 2, 3]), true);
* ```
*
* @category guards
* @since 2.0.0
*/
<T>(self: T): self is Extract<T, ReadonlyArray<any>>
} = Array.isArray
/**
* Determine if an `Array` is empty narrowing down the type to `[]`.
*
* @param self - The `Array` to check.
*
* @example
* ```ts
* import { isEmptyArray } from "effect/Array"
*
* assert.deepStrictEqual(isEmptyArray([]), true);
* assert.deepStrictEqual(isEmptyArray([1, 2, 3]), false);
* ```
*
* @category guards
* @since 2.0.0
*/
export const isEmptyArray = <A>(self: Array<A>): self is [] => self.length === 0
/**
* Determine if a `ReadonlyArray` is empty narrowing down the type to `readonly []`.
*
* @param self - The `ReadonlyArray` to check.
*
* @example
* ```ts
* import { isEmptyReadonlyArray } from "effect/Array"
*
* assert.deepStrictEqual(isEmptyReadonlyArray([]), true);
* assert.deepStrictEqual(isEmptyReadonlyArray([1, 2, 3]), false);
* ```
*
* @category guards
* @since 2.0.0
*/
export const isEmptyReadonlyArray: <A>(self: ReadonlyArray<A>) => self is readonly [] = isEmptyArray as any
/**
* Determine if an `Array` is non empty narrowing down the type to `NonEmptyArray`.
*
* An `Array` is considered to be a `NonEmptyArray` if it contains at least one element.
*
* @param self - The `Array` to check.
*
* @example
* ```ts
* import { isNonEmptyArray } from "effect/Array"
*
* assert.deepStrictEqual(isNonEmptyArray([]), false);
* assert.deepStrictEqual(isNonEmptyArray([1, 2, 3]), true);
* ```
*
* @category guards
* @since 2.0.0
*/
export const isNonEmptyArray: <A>(self: Array<A>) => self is NonEmptyArray<A> = readonlyArray.isNonEmptyArray
/**
* Determine if a `ReadonlyArray` is non empty narrowing down the type to `NonEmptyReadonlyArray`.
*
* A `ReadonlyArray` is considered to be a `NonEmptyReadonlyArray` if it contains at least one element.
*
* @param self - The `ReadonlyArray` to check.
*
* @example
* ```ts
* import { isNonEmptyReadonlyArray } from "effect/Array"
*
* assert.deepStrictEqual(isNonEmptyReadonlyArray([]), false);
* assert.deepStrictEqual(isNonEmptyReadonlyArray([1, 2, 3]), true);
* ```
*
* @category guards
* @since 2.0.0
*/
export const isNonEmptyReadonlyArray: <A>(self: ReadonlyArray<A>) => self is NonEmptyReadonlyArray<A> =
readonlyArray.isNonEmptyArray
/**
* Return the number of elements in a `ReadonlyArray`.
*
* @category getters
* @since 2.0.0
*/
export const length = <A>(self: ReadonlyArray<A>): number => self.length
const isOutOfBound = <A>(i: number, as: ReadonlyArray<A>): boolean => i < 0 || i >= as.length
const clamp = <A>(i: number, as: ReadonlyArray<A>): number => Math.floor(Math.min(Math.max(0, i), as.length))
/**
* This function provides a safe way to read a value at a particular index from a `ReadonlyArray`.
*
* @category getters
* @since 2.0.0
*/
export const get: {
/**
* This function provides a safe way to read a value at a particular index from a `ReadonlyArray`.
*
* @category getters
* @since 2.0.0
*/
(index: number): <A>(self: ReadonlyArray<A>) => Option<A>
/**
* This function provides a safe way to read a value at a particular index from a `ReadonlyArray`.
*
* @category getters
* @since 2.0.0
*/
<A>(self: ReadonlyArray<A>, index: number): Option<A>
} = dual(2, <A>(self: ReadonlyArray<A>, index: number): Option<A> => {
const i = Math.floor(index)
return isOutOfBound(i, self) ? O.none() : O.some(self[i])
})
/**
* Gets an element unsafely, will throw on out of bounds.
*
* @since 2.0.0
* @category unsafe
*/
export const unsafeGet: {
/**
* Gets an element unsafely, will throw on out of bounds.
*
* @since 2.0.0
* @category unsafe
*/
(index: number): <A>(self: ReadonlyArray<A>) => A
/**
* Gets an element unsafely, will throw on out of bounds.
*
* @since 2.0.0
* @category unsafe
*/
<A>(self: ReadonlyArray<A>, index: number): A
} = dual(2, <A>(self: ReadonlyArray<A>, index: number): A => {
const i = Math.floor(index)
if (isOutOfBound(i, self)) {
throw new Error(`Index ${i} out of bounds`)
}
return self[i]
})
/**
* Return a tuple containing the first element, and a new `Array` of the remaining elements, if any.
*
* @example
* ```ts
* import { Array } from "effect";
*
* const result = Array.unprepend([1, 2, 3, 4])
* assert.deepStrictEqual(result, [1, [2, 3, 4]])
* ```
*
* @category splitting
* @since 2.0.0
*/
export const unprepend = <A>(
self: NonEmptyReadonlyArray<A>
): [firstElement: A, remainingElements: Array<A>] => [headNonEmpty(self), tailNonEmpty(self)]
/**
* Return a tuple containing a copy of the `NonEmptyReadonlyArray` without its last element, and that last element.
*
* @example
* ```ts
* import { Array } from "effect";
*
* const result = Array.unappend([1, 2, 3, 4])
* assert.deepStrictEqual(result, [[1, 2, 3], 4])
* ```
*
* @category splitting
* @since 2.0.0
*/
export const unappend = <A>(
self: NonEmptyReadonlyArray<A>
): [arrayWithoutLastElement: Array<A>, lastElement: A] => [initNonEmpty(self), lastNonEmpty(self)]
/**
* Get the first element of a `ReadonlyArray`, or `None` if the `ReadonlyArray` is empty.
*
* @category getters
* @since 2.0.0
*/
export const head: <A>(self: ReadonlyArray<A>) => Option<A> = get(0)
/**
* Get the first element of a non empty array.
*
* @example
* ```ts
* import { Array } from "effect"
*
* const result = Array.headNonEmpty([1, 2, 3, 4])
* assert.deepStrictEqual(result, 1)
* ```
*
* @category getters
* @since 2.0.0
*/
export const headNonEmpty: <A>(self: NonEmptyReadonlyArray<A>) => A = unsafeGet(0)
/**
* Get the last element in a `ReadonlyArray`, or `None` if the `ReadonlyArray` is empty.
*
* @category getters
* @since 2.0.0
*/
export const last = <A>(self: ReadonlyArray<A>): Option<A> =>
isNonEmptyReadonlyArray(self) ? O.some(lastNonEmpty(self)) : O.none()
/**
* Get the last element of a non empty array.
*
* @example
* ```ts
* import { Array } from "effect"
*
* const result = Array.lastNonEmpty([1, 2, 3, 4])
* assert.deepStrictEqual(result, 4)
* ```
*
* @category getters
* @since 2.0.0
*/
export const lastNonEmpty = <A>(self: NonEmptyReadonlyArray<A>): A => self[self.length - 1]
/**
* Get all but the first element of an `Iterable`, creating a new `Array`, or `None` if the `Iterable` is empty.
*
* @category getters
* @since 2.0.0
*/
export const tail = <A>(self: Iterable<A>): Option<Array<A>> => {
const input = fromIterable(self)
return isNonEmptyReadonlyArray(input) ? O.some(tailNonEmpty(input)) : O.none()
}
/**
* Get all but the first element of a `NonEmptyReadonlyArray`.
*
* @example
* ```ts
* import { Array } from "effect"
*
* const result = Array.tailNonEmpty([1, 2, 3, 4])
* assert.deepStrictEqual(result, [2, 3, 4])
* ```
*
* @category getters
* @since 2.0.0
*/
export const tailNonEmpty = <A>(self: NonEmptyReadonlyArray<A>): Array<A> => self.slice(1)
/**
* Get all but the last element of an `Iterable`, creating a new `Array`, or `None` if the `Iterable` is empty.
*
* @category getters
* @since 2.0.0
*/
export const init = <A>(self: Iterable<A>): Option<Array<A>> => {
const input = fromIterable(self)
return isNonEmptyReadonlyArray(input) ? O.some(initNonEmpty(input)) : O.none()
}
/**
* Get all but the last element of a non empty array, creating a new array.
*
* @example
* ```ts
* import { Array } from "effect"
*
* const result = Array.initNonEmpty([1, 2, 3, 4])
* assert.deepStrictEqual(result, [1, 2, 3])
* ```
*
* @category getters
* @since 2.0.0
*/
export const initNonEmpty = <A>(self: NonEmptyReadonlyArray<A>): Array<A> => self.slice(0, -1)
/**
* Keep only a max number of elements from the start of an `Iterable`, creating a new `Array`.
*
* **Note**. `n` is normalized to a non negative integer.
*
* @example
* ```ts
* import { Array } from "effect"
*
* const numbers = [1, 2, 3, 4, 5]
* const result = Array.take(numbers, 3)
* assert.deepStrictEqual(result, [1, 2, 3])
* ```
*
* @category getters
* @since 2.0.0
*/
export const take: {
/**
* Keep only a max number of elements from the start of an `Iterable`, creating a new `Array`.
*
* **Note**. `n` is normalized to a non negative integer.
*
* @example
* ```ts
* import { Array } from "effect"
*
* const numbers = [1, 2, 3, 4, 5]
* const result = Array.take(numbers, 3)
* assert.deepStrictEqual(result, [1, 2, 3])
* ```
*
* @category getters
* @since 2.0.0
*/
(n: number): <A>(self: Iterable<A>) => Array<A>
/**
* Keep only a max number of elements from the start of an `Iterable`, creating a new `Array`.
*
* **Note**. `n` is normalized to a non negative integer.
*
* @example
* ```ts
* import { Array } from "effect"
*
* const numbers = [1, 2, 3, 4, 5]
* const result = Array.take(numbers, 3)
* assert.deepStrictEqual(result, [1, 2, 3])
* ```
*
* @category getters
* @since 2.0.0
*/
<A>(self: Iterable<A>, n: number): Array<A>
} = dual(2, <A>(self: Iterable<A>, n: number): Array<A> => {
const input = fromIterable(self)
return input.slice(0, clamp(n, input))
})
/**
* Keep only a max number of elements from the end of an `Iterable`, creating a new `Array`.
*
* **Note**. `n` is normalized to a non negative integer.
*
* @example
* ```ts
* import { Array } from "effect"
*
* const numbers = [1, 2, 3, 4, 5]
* const result = Array.takeRight(numbers, 3)
* assert.deepStrictEqual(result, [3, 4, 5])
* ```
*
* @category getters
* @since 2.0.0
*/
export const takeRight: {
/**
* Keep only a max number of elements from the end of an `Iterable`, creating a new `Array`.
*
* **Note**. `n` is normalized to a non negative integer.
*
* @example
* ```ts
* import { Array } from "effect"
*
* const numbers = [1, 2, 3, 4, 5]
* const result = Array.takeRight(numbers, 3)
* assert.deepStrictEqual(result, [3, 4, 5])
* ```
*
* @category getters
* @since 2.0.0
*/
(n: number): <A>(self: Iterable<A>) => Array<A>
/**
* Keep only a max number of elements from the end of an `Iterable`, creating a new `Array`.
*
* **Note**. `n` is normalized to a non negative integer.
*
* @example
* ```ts
* import { Array } from "effect"
*
* const numbers = [1, 2, 3, 4, 5]
* const result = Array.takeRight(numbers, 3)
* assert.deepStrictEqual(result, [3, 4, 5])
* ```
*
* @category getters
* @since 2.0.0
*/
<A>(self: Iterable<A>, n: number): Array<A>
} = dual(2, <A>(self: Iterable<A>, n: number): Array<A> => {
const input = fromIterable(self)
const i = clamp(n, input)
return i === 0 ? [] : input.slice(-i)
})
/**
* Calculate the longest initial subarray for which all element satisfy the specified predicate, creating a new `Array`.
*
* @example
* ```ts
* import { Array } from "effect"
*
* const numbers = [1, 3, 2, 4, 1, 2]
* const result = Array.takeWhile(numbers, x => x < 4)
* assert.deepStrictEqual(result, [1, 3, 2])
*
* // Explanation:
* // - The function starts with the first element (`1`), which is less than `4`, so it adds `1` to the result.
* // - The next element (`3`) is also less than `4`, so it adds `3`.
* // - The next element (`2`) is again less than `4`, so it adds `2`.
* // - The function then encounters `4`, which is not less than `4`. At this point, it stops checking further elements and finalizes the result.
* ```
*
* @category getters
* @since 2.0.0
*/
export const takeWhile: {
/**
* Calculate the longest initial subarray for which all element satisfy the specified predicate, creating a new `Array`.
*
* @example
* ```ts
* import { Array } from "effect"
*
* const numbers = [1, 3, 2, 4, 1, 2]
* const result = Array.takeWhile(numbers, x => x < 4)
* assert.deepStrictEqual(result, [1, 3, 2])
*
* // Explanation:
* // - The function starts with the first element (`1`), which is less than `4`, so it adds `1` to the result.
* // - The next element (`3`) is also less than `4`, so it adds `3`.
* // - The next element (`2`) is again less than `4`, so it adds `2`.
* // - The function then encounters `4`, which is not less than `4`. At this point, it stops checking further elements and finalizes the result.
* ```
*
* @category getters
* @since 2.0.0
*/
<A, B extends A>(refinement: (a: NoInfer<A>, i: number) => a is B): (self: Iterable<A>) => Array<B>
/**
* Calculate the longest initial subarray for which all element satisfy the specified predicate, creating a new `Array`.
*
* @example
* ```ts
* import { Array } from "effect"
*
* const numbers = [1, 3, 2, 4, 1, 2]
* const result = Array.takeWhile(numbers, x => x < 4)
* assert.deepStrictEqual(result, [1, 3, 2])
*
* // Explanation:
* // - The function starts with the first element (`1`), which is less than `4`, so it adds `1` to the result.
* // - The next element (`3`) is also less than `4`, so it adds `3`.
* // - The next element (`2`) is again less than `4`, so it adds `2`.
* // - The function then encounters `4`, which is not less than `4`. At this point, it stops checking further elements and finalizes the result.
* ```
*
* @category getters
* @since 2.0.0
*/
<A>(predicate: (a: NoInfer<A>, i: number) => boolean): (self: Iterable<A>) => Array<A>
/**
* Calculate the longest initial subarray for which all element satisfy the specified predicate, creating a new `Array`.
*
* @example
* ```ts
* import { Array } from "effect"
*
* const numbers = [1, 3, 2, 4, 1, 2]
* const result = Array.takeWhile(numbers, x => x < 4)
* assert.deepStrictEqual(result, [1, 3, 2])
*
* // Explanation:
* // - The function starts with the first element (`1`), which is less than `4`, so it adds `1` to the result.
* // - The next element (`3`) is also less than `4`, so it adds `3`.
* // - The next element (`2`) is again less than `4`, so it adds `2`.
* // - The function then encounters `4`, which is not less than `4`. At this point, it stops checking further elements and finalizes the result.
* ```
*
* @category getters
* @since 2.0.0
*/
<A, B extends A>(self: Iterable<A>, refinement: (a: A, i: number) => a is B): Array<B>
/**
* Calculate the longest initial subarray for which all element satisfy the specified predicate, creating a new `Array`.
*
* @example
* ```ts
* import { Array } from "effect"
*
* const numbers = [1, 3, 2, 4, 1, 2]
* const result = Array.takeWhile(numbers, x => x < 4)
* assert.deepStrictEqual(result, [1, 3, 2])
*
* // Explanation:
* // - The function starts with the first element (`1`), which is less than `4`, so it adds `1` to the result.
* // - The next element (`3`) is also less than `4`, so it adds `3`.
* // - The next element (`2`) is again less than `4`, so it adds `2`.
* // - The function then encounters `4`, which is not less than `4`. At this point, it stops checking further elements and finalizes the result.
* ```
*
* @category getters
* @since 2.0.0
*/
<A>(self: Iterable<A>, predicate: (a: A, i: number) => boolean): Array<A>
} = dual(2, <A>(self: Iterable<A>, predicate: (a: A, i: number) => boolean): Array<A> => {
let i = 0
const out: Array<A> = []
for (const a of self) {
if (!predicate(a, i)) {
break
}
out.push(a)
i++
}
return out
})
const spanIndex = <A>(self: Iterable<A>, predicate: (a: A, i: number) => boolean): number => {
let i = 0
for (const a of self) {
if (!predicate(a, i)) {
break
}
i++
}
return i
}
/**
* Split an `Iterable` into two parts:
*
* 1. the longest initial subarray for which all elements satisfy the specified predicate
* 2. the remaining elements
*
* @category splitting
* @since 2.0.0
*/
export const span: {
/**
* Split an `Iterable` into two parts:
*
* 1. the longest initial subarray for which all elements satisfy the specified predicate
* 2. the remaining elements
*
* @category splitting
* @since 2.0.0
*/
<A, B extends A>(refinement: (a: NoInfer<A>, i: number) => a is B): (self: Iterable<A>) => [init: Array<B>, rest: Array<Exclude<A, B>>]
/**
* Split an `Iterable` into two parts:
*
* 1. the longest initial subarray for which all elements satisfy the specified predicate
* 2. the remaining elements
*
* @category splitting
* @since 2.0.0
*/
<A>(predicate: (a: NoInfer<A>, i: number) => boolean): (self: Iterable<A>) => [init: Array<A>, rest: Array<A>]
/**
* Split an `Iterable` into two parts:
*
* 1. the longest initial subarray for which all elements satisfy the specified predicate
* 2. the remaining elements
*
* @category splitting
* @since 2.0.0
*/
<A, B extends A>(self: Iterable<A>, refinement: (a: A, i: number) => a is B): [init: Array<B>, rest: Array<Exclude<A, B>>]
/**
* Split an `Iterable` into two parts:
*
* 1. the longest initial subarray for which all elements satisfy the specified predicate
* 2. the remaining elements
*
* @category splitting
* @since 2.0.0
*/
<A>(self: Iterable<A>, predicate: (a: A, i: number) => boolean): [init: Array<A>, rest: Array<A>]
} = dual(
2,
<A>(self: Iterable<A>, predicate: (a: A, i: number) => boolean): [init: Array<A>, rest: Array<A>] =>
splitAt(self, spanIndex(self, predicate))
)
/**
* Drop a max number of elements from the start of an `Iterable`, creating a new `Array`.
*
* **Note**. `n` is normalized to a non negative integer.
*
* @example
* ```ts
* import { Array } from "effect"
*
* const numbers = [1, 2, 3, 4, 5]
* const result = Array.drop(numbers, 2)
* assert.deepStrictEqual(result, [3, 4, 5])
* ```
*
* @category getters
* @since 2.0.0
*/
export const drop: {
/**
* Drop a max number of elements from the start of an `Iterable`, creating a new `Array`.
*
* **Note**. `n` is normalized to a non negative integer.
*
* @example
* ```ts
* import { Array } from "effect"
*
* const numbers = [1, 2, 3, 4, 5]
* const result = Array.drop(numbers, 2)
* assert.deepStrictEqual(result, [3, 4, 5])
* ```
*
* @category getters
* @since 2.0.0
*/
(n: number): <A>(self: Iterable<A>) => Array<A>
/**
* Drop a max number of elements from the start of an `Iterable`, creating a new `Array`.
*
* **Note**. `n` is normalized to a non negative integer.
*
* @example
* ```ts
* import { Array } from "effect"
*
* const numbers = [1, 2, 3, 4, 5]
* const result = Array.drop(numbers, 2)
* assert.deepStrictEqual(result, [3, 4, 5])
* ```
*
* @category getters
* @since 2.0.0
*/
<A>(self: Iterable<A>, n: number): Array<A>
} = dual(2, <A>(self: Iterable<A>, n: number): Array<A> => {
const input = fromIterable(self)
return input.slice(clamp(n, input), input.length)
})
/**
* Drop a max number of elements from the end of an `Iterable`, creating a new `Array`.
*
* **Note**. `n` is normalized to a non negative integer.
*
* @example
* ```ts
* import { Array } from "effect"
*
* const numbers = [1, 2, 3, 4, 5]
* const result = Array.dropRight(numbers, 2)
* assert.deepStrictEqual(result, [1, 2, 3])
* ```
*
* @category getters
* @since 2.0.0
*/
export const dropRight: {
/**
* Drop a max number of elements from the end of an `Iterable`, creating a new `Array`.
*
* **Note**. `n` is normalized to a non negative integer.
*
* @example
* ```ts
* import { Array } from "effect"
*
* const numbers = [1, 2, 3, 4, 5]
* const result = Array.dropRight(numbers, 2)
* assert.deepStrictEqual(result, [1, 2, 3])
* ```
*
* @category getters
* @since 2.0.0
*/
(n: number): <A>(self: Iterable<A>) => Array<A>
/**
* Drop a max number of elements from the end of an `Iterable`, creating a new `Array`.
*
* **Note**. `n` is normalized to a non negative integer.
*
* @example
* ```ts
* import { Array } from "effect"
*
* const numbers = [1, 2, 3, 4, 5]
* const result = Array.dropRight(numbers, 2)
* assert.deepStrictEqual(result, [1, 2, 3])
* ```
*
* @category getters
* @since 2.0.0
*/
<A>(self: Iterable<A>, n: number): Array<A>
} = dual(2, <A>(self: Iterable<A>, n: number): Array<A> => {
const input = fromIterable(self)
return input.slice(0, input.length - clamp(n, input))
})
/**
* Remove the longest initial subarray for which all element satisfy the specified predicate, creating a new `Array`.
*
* @example
* ```ts
* import { Array } from "effect"
*
* const numbers = [1, 2, 3, 4, 5]
* const result = Array.dropWhile(numbers, x => x < 4)
* assert.deepStrictEqual(result, [4, 5])
* ```
*
* @category getters
* @since 2.0.0
*/
export const dropWhile: {
/**
* Remove the longest initial subarray for which all element satisfy the specified predicate, creating a new `Array`.
*
* @example
* ```ts
* import { Array } from "effect"
*
* const numbers = [1, 2, 3, 4, 5]
* const result = Array.dropWhile(numbers, x => x < 4)
* assert.deepStrictEqual(result, [4, 5])
* ```
*
* @category getters
* @since 2.0.0
*/
<A>(predicate: (a: NoInfer<A>, i: number) => boolean): (self: Iterable<A>) => Array<A>
/**
* Remove the longest initial subarray for which all element satisfy the specified predicate, creating a new `Array`.
*
* @example
* ```ts
* import { Array } from "effect"
*
* const numbers = [1, 2, 3, 4, 5]
* const result = Array.dropWhile(numbers, x => x < 4)
* assert.deepStrictEqual(result, [4, 5])
* ```
*
* @category getters
* @since 2.0.0
*/
<A>(self: Iterable<A>, predicate: (a: A, i: number) => boolean): Array<A>
} = dual(
2,
<A>(self: Iterable<A>, predicate: (a: A, i: number) => boolean): Array<A> =>
fromIterable(self).slice(spanIndex(self, predicate))
)
/**
* Return the first index for which a predicate holds.
*
* @example
* ```ts
* import { Array, Option } from "effect"
*
* const numbers = [5, 3, 8, 9]
* const result = Array.findFirstIndex(numbers, x => x > 5)
* assert.deepStrictEqual(result, Option.some(2))
* ```
*
* @category elements
* @since 2.0.0
*/
export const findFirstIndex: {
/**
* Return the first index for which a predicate holds.
*
* @example
* ```ts
* import { Array, Option } from "effect"
*
* const numbers = [5, 3, 8, 9]
* const result = Array.findFirstIndex(numbers, x => x > 5)
* assert.deepStrictEqual(result, Option.some(2))
* ```
*
* @category elements
* @since 2.0.0
*/
<A>(predicate: (a: NoInfer<A>, i: number) => boolean): (self: Iterable<A>) => Option<number>
/**
* Return the first index for which a predicate holds.
*
* @example
* ```ts
* import { Array, Option } from "effect"
*
* const numbers = [5, 3, 8, 9]
* const result = Array.findFirstIndex(numbers, x => x > 5)
* assert.deepStrictEqual(result, Option.some(2))
* ```
*
* @category elements
* @since 2.0.0
*/
<A>(self: Iterable<A>, predicate: (a: A, i: number) => boolean): Option<number>
} = dual(2, <A>(self: Iterable<A>, predicate: (a: A, i: number) => boolean): Option<number> => {
let i = 0
for (const a of self) {
if (predicate(a, i)) {
return O.some(i)
}
i++
}
return O.none()
})
/**
* Return the last index for which a predicate holds.
*
* @example
* ```ts
* import { Array, Option } from "effect"
*
* const numbers = [1, 3, 8, 9]
* const result = Ar