UNPKG

effect

Version:

The missing standard library for TypeScript, for writing production-grade software.

1,653 lines (1,651 loc) 76.9 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.rotate = exports.reverse = exports.replicate = exports.replaceOption = exports.replace = exports.remove = exports.reduceRight = exports.reduce = exports.range = exports.prependAll = exports.prepend = exports.partitionMap = exports.partition = exports.pad = exports.of = exports.modifyOption = exports.modifyNonEmptyLast = exports.modifyNonEmptyHead = exports.modify = exports.min = exports.max = exports.matchRight = exports.matchLeft = exports.match = exports.mapAccum = exports.map = exports.makeBy = exports.make = exports.liftPredicate = exports.liftOption = exports.liftNullable = exports.liftEither = exports.let = exports.length = exports.lastNonEmpty = exports.last = exports.join = exports.isNonEmptyReadonlyArray = exports.isNonEmptyArray = exports.isEmptyReadonlyArray = exports.isEmptyArray = exports.isArray = exports.intersperse = exports.intersectionWith = exports.intersection = exports.insertAt = exports.initNonEmpty = exports.init = exports.headNonEmpty = exports.head = exports.groupWith = exports.groupBy = exports.group = exports.getSomes = exports.getRights = exports.getOrder = exports.getLefts = exports.getEquivalence = exports.get = exports.fromRecord = exports.fromOption = exports.fromNullable = exports.fromIterable = exports.forEach = exports.flatten = exports.flatMapNullable = exports.flatMap = exports.findLastIndex = exports.findLast = exports.findFirstIndex = exports.findFirst = exports.filterMapWhile = exports.filterMap = exports.filter = exports.extend = exports.every = exports.ensure = exports.empty = exports.dropWhile = exports.dropRight = exports.drop = exports.differenceWith = exports.difference = exports.dedupeWith = exports.dedupeAdjacentWith = exports.dedupeAdjacent = exports.dedupe = exports.copy = exports.containsWith = exports.contains = exports.chunksOf = exports.chop = exports.cartesianWith = exports.cartesian = exports.bindTo = exports.bind = exports.appendAll = exports.append = exports.allocate = exports.Do = void 0; exports.zipWith = exports.zip = exports.unzip = exports.unsafeGet = exports.unprepend = exports.unionWith = exports.union = exports.unfold = exports.unappend = exports.takeWhile = exports.takeRight = exports.take = exports.tailNonEmpty = exports.tail = exports.splitWhere = exports.splitNonEmptyAt = exports.splitAt = exports.split = exports.span = exports.sortWith = exports.sortBy = exports.sort = exports.some = exports.setNonEmptyLast = exports.setNonEmptyHead = exports.separate = exports.scanRight = exports.scan = void 0; var E = _interopRequireWildcard(require("./Either.js")); var Equal = _interopRequireWildcard(require("./Equal.js")); var Equivalence = _interopRequireWildcard(require("./Equivalence.js")); var _Function = require("./Function.js"); var readonlyArray = _interopRequireWildcard(require("./internal/array.js")); var doNotation = _interopRequireWildcard(require("./internal/doNotation.js")); var EffectIterable = _interopRequireWildcard(require("./Iterable.js")); var O = _interopRequireWildcard(require("./Option.js")); var Order = _interopRequireWildcard(require("./Order.js")); var _Predicate = require("./Predicate.js"); var Record = _interopRequireWildcard(require("./Record.js")); var Tuple = _interopRequireWildcard(require("./Tuple.js")); function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); } function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; } /** * This module provides utility functions for working with arrays in TypeScript. * * @since 2.0.0 */ /** * 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 */ const make = (...elements) => 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 */ exports.make = make; const allocate = n => 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 */ exports.allocate = allocate; const makeBy = exports.makeBy = /*#__PURE__*/(0, _Function.dual)(2, (n, f) => { 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; }); /** * 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 */ const range = (start, end) => 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 */ exports.range = range; const replicate = exports.replicate = /*#__PURE__*/(0, _Function.dual)(2, (a, n) => 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 */ const fromIterable = collection => 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 */ exports.fromIterable = fromIterable; const ensure = self => Array.isArray(self) ? self : [self]; /** * 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 */ exports.ensure = ensure; const fromRecord = exports.fromRecord = 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 */ const fromOption = exports.fromOption = 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 */ const match = exports.match = /*#__PURE__*/(0, _Function.dual)(2, (self, { onEmpty, onNonEmpty }) => 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 */ const matchLeft = exports.matchLeft = /*#__PURE__*/(0, _Function.dual)(2, (self, { onEmpty, onNonEmpty }) => 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 */ const matchRight = exports.matchRight = /*#__PURE__*/(0, _Function.dual)(2, (self, { onEmpty, onNonEmpty }) => 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 */ const prepend = exports.prepend = /*#__PURE__*/(0, _Function.dual)(2, (self, head) => [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 */ const prependAll = exports.prependAll = /*#__PURE__*/(0, _Function.dual)(2, (self, that) => 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 */ const append = exports.append = /*#__PURE__*/(0, _Function.dual)(2, (self, last) => [...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 */ const appendAll = exports.appendAll = /*#__PURE__*/(0, _Function.dual)(2, (self, that) => 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 */ const scan = exports.scan = /*#__PURE__*/(0, _Function.dual)(3, (self, b, f) => { const out = [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 */ const scanRight = exports.scanRight = /*#__PURE__*/(0, _Function.dual)(3, (self, b, f) => { const input = fromIterable(self); const out = new Array(input.length + 1); 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 */ const isArray = exports.isArray = 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 */ const isEmptyArray = self => 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 */ exports.isEmptyArray = isEmptyArray; const isEmptyReadonlyArray = exports.isEmptyReadonlyArray = isEmptyArray; /** * 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 */ const isNonEmptyArray = exports.isNonEmptyArray = 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 */ const isNonEmptyReadonlyArray = exports.isNonEmptyReadonlyArray = readonlyArray.isNonEmptyArray; /** * Return the number of elements in a `ReadonlyArray`. * * @category getters * @since 2.0.0 */ const length = self => self.length; exports.length = length; const isOutOfBound = (i, as) => i < 0 || i >= as.length; const clamp = (i, as) => 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 */ const get = exports.get = /*#__PURE__*/(0, _Function.dual)(2, (self, index) => { 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 */ const unsafeGet = exports.unsafeGet = /*#__PURE__*/(0, _Function.dual)(2, (self, index) => { 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 */ const unprepend = self => [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 */ exports.unprepend = unprepend; const unappend = self => [initNonEmpty(self), lastNonEmpty(self)]; /** * Get the first element of a `ReadonlyArray`, or `None` if the `ReadonlyArray` is empty. * * @category getters * @since 2.0.0 */ exports.unappend = unappend; const head = exports.head = /*#__PURE__*/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 */ const headNonEmpty = exports.headNonEmpty = /*#__PURE__*/unsafeGet(0); /** * Get the last element in a `ReadonlyArray`, or `None` if the `ReadonlyArray` is empty. * * @category getters * @since 2.0.0 */ const last = self => 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 */ exports.last = last; const lastNonEmpty = self => 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 */ exports.lastNonEmpty = lastNonEmpty; const tail = self => { 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 */ exports.tail = tail; const tailNonEmpty = self => 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 */ exports.tailNonEmpty = tailNonEmpty; const init = self => { 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 */ exports.init = init; const initNonEmpty = self => 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 */ exports.initNonEmpty = initNonEmpty; const take = exports.take = /*#__PURE__*/(0, _Function.dual)(2, (self, n) => { 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 */ const takeRight = exports.takeRight = /*#__PURE__*/(0, _Function.dual)(2, (self, n) => { 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 */ const takeWhile = exports.takeWhile = /*#__PURE__*/(0, _Function.dual)(2, (self, predicate) => { let i = 0; const out = []; for (const a of self) { if (!predicate(a, i)) { break; } out.push(a); i++; } return out; }); const spanIndex = (self, predicate) => { 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 */ const span = exports.span = /*#__PURE__*/(0, _Function.dual)(2, (self, predicate) => 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 */ const drop = exports.drop = /*#__PURE__*/(0, _Function.dual)(2, (self, n) => { 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 */ const dropRight = exports.dropRight = /*#__PURE__*/(0, _Function.dual)(2, (self, n) => { 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 */ const dropWhile = exports.dropWhile = /*#__PURE__*/(0, _Function.dual)(2, (self, predicate) => 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 */ const findFirstIndex = exports.findFirstIndex = /*#__PURE__*/(0, _Function.dual)(2, (self, predicate) => { 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 = Array.findLastIndex(numbers, x => x < 5) * assert.deepStrictEqual(result, Option.some(1)) * ``` * * @category elements * @since 2.0.0 */ const findLastIndex = exports.findLastIndex = /*#__PURE__*/(0, _Function.dual)(2, (self, predicate) => { const input = fromIterable(self); for (let i = input.length - 1; i >= 0; i--) { if (predicate(input[i], i)) { return O.some(i); } } return O.none(); }); /** * Returns the first element that satisfies the specified * predicate, or `None` if no such element exists. * * @example * ```ts * import { Array, Option } from "effect" * * const numbers = [1, 2, 3, 4, 5] * const result = Array.findFirst(numbers, x => x > 3) * assert.deepStrictEqual(result, Option.some(4)) * ``` * * @category elements * @since 2.0.0 */ const findFirst = exports.findFirst = EffectIterable.findFirst; /** * Finds the last element in an iterable collection that satisfies the given predicate or refinement. * Returns an `Option` containing the found element, or `Option.none` if no element matches. * * @example * ```ts * import { Array, Option } from "effect" * * const numbers = [1, 2, 3, 4, 5] * const result = Array.findLast(numbers, n => n % 2 === 0) * assert.deepStrictEqual(result, Option.some(4)) * ``` * * @category elements * @since 2.0.0 */ const findLast = exports.findLast = /*#__PURE__*/(0, _Function.dual)(2, (self, f) => { const input = fromIterable(self); for (let i = input.length - 1; i >= 0; i--) { const a = input[i]; const o = f(a, i); if ((0, _Predicate.isBoolean)(o)) { if (o) { return O.some(a); } } else { if (O.isSome(o)) { return o; } } } return O.none(); }); /** * Insert an element at the specified index, creating a new `NonEmptyArray`, * or return `None` if the index is out of bounds. * * @example * ```ts * import { Array, Option } from "effect" * * const letters = ['a', 'b', 'c', 'e'] * const result = Array.insertAt(letters, 3, 'd') * assert.deepStrictEqual(result, Option.some(['a', 'b', 'c', 'd', 'e'])) * ``` * * @since 2.0.0 */ const insertAt = exports.insertAt = /*#__PURE__*/(0, _Function.dual)(3, (self, i, b) => { const out = Array.from(self); // v--- `= self.length` is ok, it means inserting in last position if (i < 0 || i > out.length) { return O.none(); } out.splice(i, 0, b); return O.some(out); }); /** * Change the element at the specified index, creating a new `Array`, * or return a copy of the input if the index is out of bounds. * * @example * ```ts * import { Array } from "effect" * * const letters = ['a', 'b', 'c', 'd'] * const result = Array.replace(letters, 1, 'z') * assert.deepStrictEqual(result, ['a', 'z', 'c', 'd']) * ``` * * @since 2.0.0 */ const replace = exports.replace = /*#__PURE__*/(0, _Function.dual)(3, (self, i, b) => modify(self, i, () => b)); /** * Replaces an element in an array with the given value, returning an option of the updated array. * * @example * ```ts * import { Array, Option } from "effect" * * const numbers = [1, 2, 3] * const result = Array.replaceOption(numbers, 1, 4) * assert.deepStrictEqual(result, Option.some([1, 4, 3])) * ``` * * @since 2.0.0 */ const replaceOption = exports.replaceOption = /*#__PURE__*/(0, _Function.dual)(3, (self, i, b) => modifyOption(self, i, () => b)); /** * Apply a function to the element at the specified index, creating a new `Array`, * or return a copy of the input if the index is out of bounds. * * @example * ```ts * import { Array } from "effect" * * const numbers = [1, 2, 3, 4] * const result = Array.modify(numbers, 2, (n) => n * 2) * assert.deepStrictEqual(result, [1, 2, 6, 4]) * ``` * * @since 2.0.0 */ const modify = exports.modify = /*#__PURE__*/(0, _Function.dual)(3, (self, i, f) => O.getOrElse(modifyOption(self, i, f), () => Array.from(self))); /** * Apply a function to the element at the specified index, creating a new `Array`, * or return `None` if the index is out of bounds. * * @example * ```ts * import { Array, Option } from "effect" * * const numbers = [1, 2, 3, 4] * const result = Array.modifyOption(numbers, 2, (n) => n * 2) * assert.deepStrictEqual(result, Option.some([1, 2, 6, 4])) * * const outOfBoundsResult = Array.modifyOption(numbers, 5, (n) => n * 2) * assert.deepStrictEqual(outOfBoundsResult, Option.none()) * ``` * * @since 2.0.0 */ const modifyOption = exports.modifyOption = /*#__PURE__*/(0, _Function.dual)(3, (self, i, f) => { const out = Array.from(self); if (isOutOfBound(i, out)) { return O.none(); } const next = f(out[i]); // @ts-expect-error out[i] = next; return O.some(out); }); /** * Delete the element at the specified index, creating a new `Array`, * or return a copy of the input if the index is out of bounds. * * @example * ```ts * import { Array } from "effect" * * const numbers = [1, 2, 3, 4] * const result = Array.remove(numbers, 2) * assert.deepStrictEqual(result, [1, 2, 4]) * * const outOfBoundsResult = Array.remove(numbers, 5) * assert.deepStrictEqual(outOfBoundsResult, [1, 2, 3, 4]) * ``` * * @since 2.0.0 */ const remove = exports.remove = /*#__PURE__*/(0, _Function.dual)(2, (self, i) => { const out = Array.from(self); if (isOutOfBound(i, out)) { return out; } out.splice(i, 1); return out; }); /** * Reverse an `Iterable`, creating a new `Array`. * * @example * ```ts * import { Array } from "effect" * * const numbers = [1, 2, 3, 4] * const result = Array.reverse(numbers) * assert.deepStrictEqual(result, [4, 3, 2, 1]) * ``` * * @category elements * @since 2.0.0 */ const reverse = self => Array.from(self).reverse(); /** * Create a new array with elements sorted in increasing order based on the specified comparator. * If the input is a `NonEmptyReadonlyArray`, the output will also be a `NonEmptyReadonlyArray`. * * @category sorting * @since 2.0.0 */ exports.reverse = reverse; const sort = exports.sort = /*#__PURE__*/(0, _Function.dual)(2, (self, O) => { const out = Array.from(self); out.sort(O); return out; }); /** * Sorts an array based on a provided mapping function and order. The mapping * function transforms the elements into a value that can be compared, and the * order defines how those values should be sorted. * * @example * ```ts * import { Array, Order } from "effect" * * const strings = ["aaa", "b", "cc"] * const result = Array.sortWith(strings, (s) => s.length, Order.number) * assert.deepStrictEqual(result, ["b", "cc", "aaa"]) * * // Explanation: * // The array of strings is sorted based on their lengths. The mapping function `(s) => s.length` * // converts each string into its length, and the `Order.number` specifies that the lengths should * // be sorted in ascending order. * ``` * * @since 2.0.0 * @category elements */ const sortWith = exports.sortWith = /*#__PURE__*/(0, _Function.dual)(3, (self, f, order) => Array.from(self).map(a => [a, f(a)]).sort((a, b) => order(a[1], b[1])).map(x => x[0])); /** * Sorts the elements of an `Iterable` in increasing order based on the provided * orders. The elements are compared using the first order in `orders`, then the * second order if the first comparison is equal, and so on. * * @example * ```ts * import { Array, Order } from "effect" * * const users = [ * { name: "Alice", age: 30 }, * { name: "Bob", age: 25 }, * { name: "Charlie", age: 30 } * ] * * const result = Array.sortBy( * Order.mapInput(Order.number, (user: (typeof users)[number]) => user.age), * Order.mapInput(Order.string, (user: (typeof users)[number]) => user.name) * )(users) * * assert.deepStrictEqual(result, [ * { name: "Bob", age: 25 }, * { name: "Alice", age: 30 }, * { name: "Charlie", age: 30 } * ]) * * // Explanation: * // The array of users is sorted first by age in ascending order. When ages are equal, * // the users are further sorted by name in ascending order. * ``` * * @category sorting * @since 2.0.0 */ const sortBy = (...orders) => { const sortByAll = sort(Order.combineAll(orders)); return self => { const input = fromIterable(self); if (isNonEmptyReadonlyArray(input)) { return sortByAll(input); } return []; }; }; /** * Takes two `Iterable`s and returns an `Array` of corresponding pairs. * If one input `Iterable` is short, excess elements of the * longer `Iterable` are discarded. * * @example * ```ts * import { Array } from "effect" * * const array1 = [1, 2, 3] * const array2 = ['a', 'b'] * const result = Array.zip(array1, array2) * assert.deepStrictEqual(result, [[1, 'a'], [2, 'b']]) * ``` * * @category zipping * @since 2.0.0 */ exports.sortBy = sortBy; const zip = exports.zip = /*#__PURE__*/(0, _Function.dual)(2, (self, that) => zipWith(self, that, Tuple.make)); /** * Apply a function to pairs of elements at the same index in two `Iterable`s, collecting the results in a new `Array`. If one * input `Iterable` is short, excess elements of the longer `Iterable` are discarded. * * @example * ```ts * import { Array } from "effect" * * const array1 = [1, 2, 3] * const array2 = [4, 5, 6] * const result = Array.zipWith(array1, array2, (a, b) => a + b) * assert.deepStrictEqual(result, [5, 7, 9]) * ``` * * @category zipping * @since 2.0.0 */ const zipWith = exports.zipWith = /*#__PURE__*/(0, _Function.dual)(3, (self, that, f) => { const as = fromIterable(self); const bs = fromIterable(that); if (isNonEmptyReadonlyArray(as) && isNonEmptyReadonlyArray(bs)) { const out = [f(headNonEmpty(as), headNonEmpty(bs))]; const len = Math.min(as.length, bs.length); for (let i = 1; i < len; i++) { out[i] = f(as[i], bs[i]); } return out; } return []; }); /** * This function is the inverse of `zip`. Takes an `Iterable` of pairs and return two corresponding `Array`s. * * @example * ```ts * import { Array } from "effect" * * const result = Array.unzip([[1, "a"], [2, "b"], [3, "c"]]) * assert.deepStrictEqual(result, [[1, 2, 3], ['a', 'b', 'c']]) * ``` * * @since 2.0.0 */ const unzip = self => { const input = fromIterable(self); if (isNonEmptyReadonlyArray(input)) { const fa = [input[0][0]]; const fb = [input[0][1]]; for (let i = 1; i < input.length; i++) { fa[i] = input[i][0]; fb[i] = input[i][1]; } return [fa, fb]; } return [[], []]; }; /** * Places an element in between members of an `Iterable`. * If the input is a non-empty array, the result is also a non-empty array. * * @example * ```ts * import { Array } from "effect" * * const numbers = [1, 2, 3] * const result = Array.intersperse(numbers, 0) * assert.deepStrictEqual(result, [1, 0, 2, 0, 3]) * ``` * * @since 2.0.0 */ exports.unzip = unzip; const intersperse = exports.intersperse = /*#__PURE__*/(0, _Function.dual)(2, (self, middle) => { const input = fromIterable(self); if (isNonEmptyReadonlyArray(input)) { const out = [headNonEmpty(input)]; const tail = tailNonEmpty(input); for (let i = 0; i < tail.length; i++) { if (i < tail.length) { out.push(middle); } out.push(tail[i]); } return out; } return []; }); /** * Apply a function to the head, creating a new `NonEmptyReadonlyArray`. * * @example * ```ts * import { Array } from "effect" * * const result = Array.modifyNonEmptyHead([1, 2, 3], n => n * 10) * assert.deepStrictEqual(result, [10, 2, 3]) * ``` * * @since 2.0.0 */ const modifyNonEmptyHead = exports.modifyNonEmptyHead = /*#__PURE__*/(0, _Function.dual)(2, (self, f) => [f(headNonEmpty(self)), ...tailNonEmpty(self)]); /** * Change the head, creating a new `NonEmptyReadonlyArray`. * * @example * ```ts * import { Array } from "effect" * * const result = Array.setNonEmptyHead([1, 2, 3], 10) * assert.deepStrictEqual(result, [10, 2, 3]) * ``` * * @since 2.0.0 */ const setNonEmptyHead = exports.setNonEmptyHead = /*#__PURE__*/(0, _Function.dual)(2, (self, b) => modifyNonEmptyHead(self, () => b)); /** * Apply a function to the last element, creating a new `NonEmptyReadonlyArray`. * * @example * ```ts * import { Array } from "effect" * * const result = Array.modifyNonEmptyLast([1, 2, 3], n => n * 2) * assert.deepStrictEqual(result, [1, 2, 6]) * ``` * * @since 2.0.0 */ const modifyNonEmptyLast = exports.modifyNonEmptyLast = /*#__PURE__*/(0, _Function.dual)(2, (self, f) => append(initNonEmpty(self), f(lastNonEmpty(self)))); /** * Change the last element, creating a new `NonEmptyReadonlyArray`. * * @example * ```ts * import { Array } from "effect" * * const result = Array.setNonEmptyLast([1, 2, 3], 4) * assert.deepStrictEqual(result, [1, 2, 4]) * ``` * * @since 2.0.0 */ const setNonEmptyLast = exports.setNonEmptyLast = /*#__PURE__*/(0, _Function.dual)(2, (self, b) => modifyNonEmptyLast(self, () => b)); /** * Rotate an `Iterable` by `n` steps. * If the input is a non-empty array, the result is also a non-empty array. * * @example * ```ts * import { Array } from "effect" * * const letters = ['a', 'b', 'c', 'd'] * const result = Array.rotate(letters, 2) * assert.deepStrictEqual(result, ['c', 'd', 'a', 'b']) * ``` * * @since 2.0.0 */ const rotate = exports.rotate = /*#__PURE__*/(0, _Function.dual)(2, (self, n) => { const input = fromIterable(self); if (isNonEmptyReadonlyArray(input)) { const len = input.length; const m = Math.round(n) % len; if (isOutOfBound(Math.abs(m), input) || m === 0) { return copy(input); } if (m < 0) { const [f, s] = splitNonEmptyAt(input, -m); return appendAll(s, f); } else { return rotate(self, m - len); } } return []; }); /** * Returns a function that checks if a `ReadonlyArray` contains a given value using a provided `isEquivalent` function. * * @example * ```ts * import { Array } from "effect" * * const numbers = [1, 2, 3, 4] * const isEquivalent = (a: number, b: number) => a === b * const containsNumber = Array.containsWith(isEquivalent) * const result = containsNumber(3)(numbers) * assert.deepStrictEqual(result, true) * ``` * * @category elements * @since 2.0.0 */ const containsWith = isEquivalent => (0, _Function.dual)(2, (self, a) => { for (const i of self) { if (isEquivalent(a, i)) { return true; } } return false; }); exports.containsWith = containsWith; const _equivalence = /*#__PURE__*/Equal.equivalence(); /** * Returns a function that checks if a `ReadonlyArray` contains a given value using the default `Equivalence`. * * @example * ```ts * import { Array } from "effect" * * const letters = ['a', 'b', 'c', 'd'] * const result = Array.contains('c')(letters) * assert.deepStrictEqual(result, true) * ``` * * @category elements * @since 2.0.0 */ const contains = exports.contains = /*#__PURE__*/containsWith(_equivalence); /** * A useful recursion pattern for processing an `Iterable` to produce a new `Array`, often used for "chopping" up the input * `Iterable`. Typically chop is called with some function that will consume an initial prefix of the `Iterable` and produce a * value and the rest of the `Array`. * * @example * ```ts * import { Array } from "effect" * * const numbers = [1, 2, 3, 4, 5] * const result = Array.chop(numbers, (as): [number, Array<number>] => [as[0] * 2, as.slice(1)]) * assert.deepStrictEqual(result, [2, 4, 6, 8, 10]) * * // Explanation: * // The `chopFunction` takes the first element of the array, doubles it, and then returns it along with the rest of the array. * // The `chop` function applies this `chopFunction` recursively to the input array `[1, 2, 3, 4, 5]`, * // resulting in a new array `[2, 4, 6, 8, 10]`. * ``` * * @since 2.0.0 */ const chop = exports.chop = /*#__PURE__*/(0, _Function.dual)(2, (self, f) => { const input = fromIterable(self); if (isNonEmptyReadonlyArray(input)) { const [b, rest] = f(input); const out = [b]; let next = rest; while (readonlyArray.isNonEmptyArray(next)) { const [b, rest] = f(next); out.push(b); next = rest; } return out; } return []; }); /** * Splits an `Iterable` into two segments, with the first segment containing a maximum of `n` elements. * The value of `n` can be `0`. * * @example * ```ts * import { Array } from "effect" * * const numbers = [1, 2, 3, 4, 5] * const result = Array.splitAt(numbers, 3) * assert.deepStrictEqual(result, [[1, 2, 3], [4, 5]]) * ``` * * @category splitting * @since 2.0.0 */ const splitAt = exports.splitAt = /*#__PURE__*/(0, _Function.dual)(2, (self, n) => { const input = Array.from(self); const _n = Math.floor(n); if (isNonEmptyReadonlyArray(input)) { if (_n >= 1) { return splitNonEmptyAt(input, _n); } return [[], input]; } return [input, []]; }); /** * Splits a `NonEmptyReadonlyArray` into two segments, with the first segment containing a maximum of `n` elements. * The value of `n` must be `>= 1`. * * @example * ```ts * import { Array } from "effect" * * const result = Array.splitNonEmptyAt(["a", "b", "c", "d", "e"], 3) * assert.deepStrictEqual(result, [["a", "b", "c"], ["d", "e"]]) * ``` * * @category splitting * @since 2.0.0 */ const splitNonEmptyAt = exports.splitNonEmptyAt = /*#__PURE__*/(0, _Function.dual)(2, (self, n) => { const _n = Math.max(1, Math.floor(n)); return _n >= self.length ? [copy(self), []] : [prepend(self.slice(1, _n), headNonEmpty(self)), self.slice(_n)]; }); /** * Splits this iterable into `n` equally sized arrays. * * @example * ```ts * import { Array } from "effect" * * const numbers = [1, 2, 3, 4, 5, 6, 7, 8] * const result = Array.split(numbers, 3) * assert.deepStrictEqual(result, [[1, 2, 3], [4, 5, 6], [7, 8]]) * ``` * * @since 2.0.0 * @category splitting */ const split = exports.split = /*#__PURE__*/(0, _Function.dual)(2, (self, n) => { const input = fromIterable(self); return chunksOf(input, Math.ceil(input.length / Math.floor(n))); }); /** * Splits this iterable on the first element that matches this predicate. * Returns a tuple containing two arrays: the first one is before the match, and the second one is from the match onward. * * @example * ```ts * import { Array } from "effect" * * const numbers = [1, 2, 3, 4, 5] * const result = Array.splitWhere(numbers, n => n > 3) * assert.deepStrictEqual(result, [[1, 2, 3], [4, 5]]) * ``` * * @category splitting * @since 2.0.0 */ const splitWhere = exports.splitWhere = /*#__PURE__*/(0, _Function.dual)(2, (self, predicate) => span(self, (a, i) => !predicate(a, i))); /** * Copies an array. * * @example * ```ts * import { Array } from "effect" * * const numbers = [1, 2, 3] * const copy = Array.copy(numbers) * assert.deepStrictEqual(copy, [1, 2, 3]) * ``` * * @since 2.0.0 */ const copy = self => self.slice(); /** * Pads an array. * Returns a new array of length `n` with the elements of `array` followed by `fill` elements if `array` is shorter than `n`. * If `array` is longer than `n`, the returned array will be a slice of `array` containing the `n` first elements of `array`. * If `n` is less than or equal to 0, the returned array will be an empty array. * * @example * ```ts * import { Array } from "effect" * * const arr = [1, 2, 3] * const result = Array.pad(arr, 6, 0) * assert.deepStrictEqual(result, [1, 2, 3, 0, 0, 0]) * ``` * * @since 3.8.4 */ exports.copy = copy; const pad = exports.pad = /*#__PURE__*/(0, _Function.dual)(3, (self, n, fill) => { if (self.length >= n) { return take(self, n); } return appendAll(self, makeBy(n - self.length, () => fill)); }); /** * Splits an `Iterable` into length-`n` pieces. The last piece will be shorter if `n` does not evenly divide the length of * the `Iterable`. Note that `chunksOf(n)([])` is `[]`, not `[[]]`. This is intentional, and is consistent with a recursive * definition of `chunksOf`; it satisfies the property that * * ```ts * chunksOf(n)(xs).concat(chunksOf(n)(ys)) == chunksOf(n)(xs.concat(ys))) * ``` * * whenever `n` evenly divides the length of `self`. * * @example * ```ts * import { Array } from "effect" * * const numbers = [1, 2, 3, 4, 5] * const result = Array.chunksOf(numbers, 2) * assert.deepStrictEqual(result, [[1, 2], [3, 4], [5]]) * * // Explanation: * // The `chunksOf` function takes an array of numbers `[1, 2, 3, 4, 5]` and a number `2`. * // It splits the array into chunks of length 2. Since the array length is not evenly divisible by 2, * // the last chunk contains the remaining elements. * // The result is `[[1, 2], [3, 4], [5]]`. * ``` * * @category splitting * @since 2.0.0 */ const chunksOf = exports.chunksOf = /*#__PURE__*/(0, _Function.dual)(2, (self, n) => { const input = fromIterable(self); if (isNonEmptyReadonlyArray(input)) { return chop(input, splitNonEmptyAt(n)); } return []; }); /** * Group equal, consecutive elements of a `NonEmptyReadonlyArray` into `NonEmptyArray`s using the provided `isEquivalent` function. * * @example * ```ts * import { Array } from "effect" * * const result = Array.groupWith(["a", "a", "b", "b", "b", "c", "a"], (x, y) => x === y) * assert.deepStrictEqual(result, [["a", "a"], ["b", "b", "b"], ["c"], ["a"]]) * ``` * * @category grouping * @since 2.0.0 */ const groupWith = exports.groupWith = /*#__PURE__*/(0, _Function.dual)(2, (self, isEquivalent) => chop(self, as => { const h = headNonEmpty(as); const out = [h]; let i = 1; for (; i < as.length; i++) { const a = as[i]; if (isEquivalent(a, h)) { out.push(a); } else { break; } } return [out, as.slice(i)]; })); /** * Group equal, consecutive elements of a `NonEmptyReadonlyArray` into `NonEmptyArray`s. * * @example * ```ts * import { Array } from "effect" * * const result = Array.group([1, 1, 2, 2, 2, 3, 1]) * assert.deepStrictEqual(result, [[1, 1], [2, 2, 2], [3], [1]]) * ``` * * @category grouping * @since 2.0.0 */ const group = exports.group = /*#__PURE__*/groupWith( /*#__PURE__*/Equal.equivalence()); /** * Splits an `Iterable` into sub-non-empty-arrays stored in an object, based on the result of calling a `string`-returning * function on each element, and grouping the results according to values returned * * @example * ```ts * import { Array } from "effect" * * const people = [ * { name: "Alice", group: "A" }, * { name: "Bob", group: "B" }, * { name: "Charlie", group: "A" } * ] * const result = Array.groupBy(people, person => person.group) * assert.deepStrictEqual(result, { * A: [{ name: "Alice", group: "A" }, { name: "Charlie", group: "A" }], * B: [{ name: "Bob", group: "B" }] * }) * ``` * * @category grouping * @since 2.0.0 */ const groupBy = exports.groupBy = /*#__PURE__*/(0, _Function.dual)(2, (self, f) => { const out = {}; for (const a of self) { const k = f(a); if (Object.prototype.hasOwnProperty.call(out, k)) { out[k].push(a); } else { out[k] = [a]; } } return out; }); /** * Calculates the union of two arrays using the provided equivalence relation. * * @example * ```ts * import { Array } from "effect" * * const array1 = [1, 2] * const array2 = [2, 3] * const union = Array.unionWith(array1, array2, (a, b) => a === b) * assert.deepStrictEqual(union, [1, 2, 3]) * ``` * * @since 2.0.0 */ const unionWith = exports.unionWith = /*#__PURE__*/(0, _Function.dual)(3, (self, that, isEquivalent) => { const a = fromIterable(self); const b = fromIterable(that); if (isNonEmptyReadonlyArray(a)) { if (isNonEmptyReadonlyArray(b)) { const dedupe = dedupeWith(isEquivalent); return dedupe(appendAll(a, b)); } return a; } return b; }); /** * Creates a union of two arrays, removing duplicates. * * @example * ```ts * import { Array } from "effect" * * const array1 = [1, 2] * const array2 = [2, 3] * const result = Array.union(array1, array2) * assert.deepStrictEqual(result, [1, 2, 3]) * ``` * * @since 2.0.0 */ const union = exports.union = /*#__PURE__*/(0, _Function.dual)(2, (self, that) => unionWith(self, that, _equivalence)); /** * Creates an `Array` of unique values that are included in all given `Iterable`s using the provided `isEquivalent` function. * The order and references of result values are determined by the first `Iterable`. * * @example * ```ts * import { Array } from "effect" * * const array1 = [{ id: 1 }