import * as ROArray from "@fp-ts/data/ReadonlyArray" import { identity } from "./Function.js" import * as Option from "./Option.js" import * as Dur from "@fp-ts/data/Duration" export * from "@fp-ts/data/ReadonlyArray" /** * @tsplus getter ets/Ord toOrder */ export function convertOrd(_: Ord): Order { return ({ compare: y => x => _.compare(x, y) }) } /** * @tsplus getter Generator toArray * @tsplus getter Iterable toArray */ export function toArray( gen: Generator ) { return Array.from(gen) } /** * Remove duplicates from an array, keeping the first occurrence of an element. * * @tsplus pipeable Array uniq * @tsplus pipeable ReadonlyArray uniq * @tsplus static fp-ts/data/ReadonlyArray.Ops uniq */ export function uniq(E: Equal) { return (self: ReadonlyArray): ReadonlyArray => { const includes = arrayIncludes(E) const result: Array = [] const length = self.length let i = 0 for (; i < length; i = i + 1) { const a = self[i]! if (!includes(result, a)) { result.push(a) } } return length === result.length ? self : result } } function arrayIncludes(E: Equal) { return (array: Array, value: A): boolean => { for (let i = 0; i < array.length; i = i + 1) { const element = array[i]! if (E.equals(value, element)) { return true } } return false } } /** * @tsplus static fp-ts/data/Duration.Ops makeMillis */ export const millis_ = Dur.millis export const { isArray } = Array // export function deleteOrOriginal_(as: ReadonlyArray, a: A) { // return as.remove(findIndexOrElse_(as, x => x === a)) // } // export function deleteAtOrOriginal(i: number) { // return (as: ReadonlyArray) => deleteAtOrOriginal_(as, i) // } // export function deleteOrOriginal(a: A) { // return (as: ReadonlyArray) => deleteOrOriginal_(as, a) // } /** * @tsplus static fp-ts/data/ReadonlyArray.Ops findFirstMap * @tsplus static Array.Ops findFirstMap * @tsplus pipeable Array findFirstMap * @tsplus pipeable fp-ts/data/ReadonlyArray findFirstMap * @tsplus pipeable ReadonlyArray findFirstMap * @tsplus pipeable NonEmptyArray findFirstMap * @tsplus pipeable NonEmptyArrayReadonlyArray findFirstMap */ export function findFirstMap( f: (a: A) => Option.Option ) { return (as: ReadonlyArray) => { const len = as.length for (let i = 0; i < len; i++) { const v = f(as[i]!) if (v.isSome()) { return v } } return Option.none } } /** * @tsplus static fp-ts/data/ReadonlyArray.NonEmptyArray.Ops fromArray */ export function NEAFromArray(ar: Array) { return ar.length ? Option.some(ar as NonEmptyArray) : Option.none } /** * @tsplus static fp-ts/data/ReadonlyArray/NonEmptyReadonlyArray.Ops fromArray */ export function NEROArrayFromArray(ar: ReadonlyArray) { return ar.length ? Option.some(ar as NonEmptyReadonlyArray) : Option.none } /** * @tsplus pipeable Array sortWith * @tsplus pipeable ReadonlyArray sortWith */ export function sortWith( ...ords: NonEmptyArguments> ): (a: ReadonlyArray) => ReadonlyArray { return ROArray.sortBy(...ords.map(convertOrd)) } /** * @tsplus pipeable Array sortByO * @tsplus pipeable ReadonlyArray sortByO * @tsplus pipeable NonEmptyArray sortByO * @tsplus pipeable NonEmptyArrayReadonlyArray sortByO */ export function sortByO( ords: Option.Option>> ): (a: ReadonlyArray) => ReadonlyArray { return ords.match(() => identity, _ => ROArray.sortBy(..._.map(convertOrd))) } /** * @tsplus fluent ReadonlyArray groupByT * @tsplus fluent Array groupByT * @tsplus fluent NonEmptyArray groupByT * @tsplus fluent NonEmptyArrayReadonlyArray groupByT */ export function groupByT( as: ReadonlyArray, f: (a: A) => Key ): ReadonlyArray]> { const r: Record & { 0: A }> = {} as any for (const a of as) { const k = f(a) // eslint-disable-next-line no-prototype-builtins if (r.hasOwnProperty(k)) { r[k]!.push(a) } else { r[k] = [a] } } return Object.entries(r).map(([k, items]) => tuple(k as unknown as Key, items as NonEmptyReadonlyArray)) } // /** // * @tsplus fluent ReadonlyArray collect // */ // export function arrayCollect(ar: readonly A[], collector: (a: A) => Option): readonly B[] { // return Chunk.fromIterable(ar).filterMap(collector).toArray // } /** * @tsplus operator ReadonlyArray & * @tsplus fluent ReadonlyArray concat */ export function concat_( self: ReadonlyArray, that: ReadonlyArray ): ReadonlyArray { return [...self, ...that] } /** * Concatenates two ReadonlyArray together * * @tsplus operator ReadonlyArray + */ export const concatOperator: ( self: ReadonlyArray, that: ReadonlyArray ) => ReadonlyArray = concat_ /** * Prepends `a` to ReadonlyArray * * @tsplus operator ReadonlyArray + 1.0 */ export function prependOperatorStrict(a: A, self: ReadonlyArray): ReadonlyArray { return ROArray.prepend(a)(self) } /** * Prepends `a` to ReadonlyArray * * @tsplus operator ReadonlyArray > */ export function prependOperator(a: A, self: ReadonlyArray): ReadonlyArray { return prepend_(self, a) } /** * Prepends `a` to ReadonlyArray * * @tsplus fluent ReadonlyArray prepend */ export function prepend_(tail: ReadonlyArray, head: B): ReadonlyArray { const len = tail.length const r = Array(len + 1) for (let i = 0; i < len; i++) { r[i + 1] = tail[i] } r[0] = head return r as unknown as ReadonlyArray } /** * Appends `a` to ReadonlyArray * * @tsplus fluent ReadonlyArray append * @tsplus operator ReadonlyArray < */ export function append_(init: ReadonlyArray, end: B): ReadonlyArray { const len = init.length const r = Array(len + 1) for (let i = 0; i < len; i++) { r[i] = init[i] } r[len] = end return r as unknown as ReadonlyArray } /** * @tsplus operator ReadonlyArray + 1.0 */ export const appendOperator: (self: ReadonlyArray, a: A) => ReadonlyArray = append_ /** * @tsplus fluent ReadonlyArray randomElement 1 * @tsplus fluent Array randomElement 1 */ export function randomElement(a: ReadonlyArray) { return a[Math.floor(Math.random() * a.length)] } /** * @tsplus fluent fp-ts/data/ReadonlyArray/NonEmptyReadonlyArray randomElement 2 */ export function randomElementNA(a: NonEmptyReadonlyArray): A { return a[Math.floor(Math.random() * a.length)] } /** * @tsplus pipeable Array mapNonEmpty * @tsplus pipeable fp-ts/data/ReadonlyArray mapNonEmpty * @tsplus pipeable fp-ts/data/ReadonlyArray/NonEmptyReadonlyArray mapNonEmpty * @tsplus pipeable fp-ts/data/ReadonlyArray.NonEmptyArray mapNonEmpty */ export const mapRA = ROArray.mapNonEmpty /** * @tsplus fluent fp-ts/data/ReadonlyArray/NonEmptyReadonlyArray sortBy */ export function sortBy(na: NonEmptyReadonlyArray, ords: readonly Ord[]) { return ROArray.sortBy(...ords.map(convertOrd))(na) as unknown as NonEmptyReadonlyArray } /** * @tsplus static fp-ts/data/ReadonlyArray.Ops sortWithNonEmpty * @tsplus pipeable ReadonlyArray sortWithNonEmpty */ export function sortWithNonEmpty( ...ords: NonEmptyArguments> ): (a: NonEmptyReadonlyArray) => NonEmptyArray { return a => a.sortByNonEmpty(...ords.map(convertOrd)) } /** * @tsplus static fp-ts/data/ReadonlyArray/NonEmptyReadonlyArray __call */ export const makeNA = ROArray.make /** * @tsplus fluent ReadonlyArray filterWith */ export function filterWith(self: ReadonlyArray, predicates: ReadonlyArray>) { return self.filter(_ => predicates.every(f => f(_))) } /** * Split the `items` array into multiple, smaller chunks of the given `size`. */ export function* _chunk_(items_: Iterable, size: number) { const items = [...items_] while (items.length) { yield items.splice(0, size) } } /** * Split the `items` array into multiple, smaller chunks of the given `size`. * @tsplus fluent Array chunk * @tsplus fluent ReadonlyArray chunk * @tsplus fluent fp-ts/data/Chunk chunk * @tsplus fluent Iterable chunk */ export function chunk_(items_: Iterable, size: number) { return Chunk.fromIterable(_chunk_(items_, size)) } /** * @tsplus getter Array toChunk * @tsplus getter ReadonlyArray toChunk * @tsplus getter Iterable toChunk */ export function toChunk(items: Iterable) { return Chunk.fromIterable(items) } /** * @tsplus getter ReadonlyArray toNonEmpty * @tsplus getter Array toNonEmpty * @tsplus getter fp-ts/data/ReadonlyArray toNonEmpty */ export const toNonEmptyArray = (a: ReadonlyArray) => a.length ? Option.some(a as NonEmptyReadonlyArray) : Option.none /** * @tsplus getter Iterable toArray * @tsplus getter Iterator toArray * @tsplus getter Generator toArray */ export const iterableToArray = Array.from /** * @tsplus getter Iterable toNonEmptyArray */ export function CollectionToNonEmptyReadonlyArray(c: Iterable) { return iterableToArray(c).toNonEmpty } /** * @tsplus getter fp-ts/data/Chunk toNonEmptyArray */ export function ChunkToNonEmptyReadonlyArray(c: Chunk) { return c.toArray.toNonEmpty } /** * @tsplus fluent Array forEachEffectPar * @tsplus fluent ReadonlyArray forEachEffectPar */ export function ext_forEachEffectPar( as: ReadonlyArray, f: (a: A) => Effect ) { return Effect.forEachPar(f)(as) } /** * @tsplus fluent fp-ts/data/Chunk forEachEffectPar */ export function ext_CNKforEachEffectPar( as: Chunk, f: (a: A) => Effect ) { return Effect.forEachPar(f)(as) } /** * @tsplus fluent fp-ts/data/ReadonlyArray/NonEmptyReadonlyArray forEachEffectPar */ export function ext_NAforEachEffectPar( as: NonEmptyReadonlyArray, f: (a: A) => Effect ) { return Effect.forEachPar(f)(as).map(_ => _.toNonEmptyArray.value!) } /** * @tsplus fluent fp-ts/data/ReadonlyArray/NonEmptyReadonlyArray forEachEffect */ export function ext_NAforEach(as: NonEmptyReadonlyArray, f: (a: A) => Effect) { return Effect.forEach(f)(as).map(_ => _.toNonEmptyArray.value!) } /** * @tsplus fluent fp-ts/data/ReadonlyArray/NonEmptyReadonlyArray forEachEffectWithIndexPar */ export function ext_NAforEachEffectWithIndexPar( as: NonEmptyReadonlyArray, f: (a: A, i: number) => Effect ) { return Effect.forEachParWithIndex(f)(as).map(_ => _.toNonEmptyArray.value!) } /** * @tsplus fluent fp-ts/data/ReadonlyArray/NonEmptyReadonlyArray forEachEffectWithIndex */ export function ext_NAforEachWithIndex( as: NonEmptyReadonlyArray, f: (a: A, i: number) => Effect ) { return Effect.forEachWithIndex(f)(as).map(_ => _.toNonEmptyArray.value!) } /** * @tsplus fluent ReadonlyArray forEachEffectWithIndex * @tsplus fluent Array forEachEffectWithIndex * @tsplus fluent fp-ts/data/Chunk forEachEffectWithIndex * @tsplus fluent ets/Set forEachEffectWithIndex */ export function ext_forEachWithIndex(as: Iterable, f: (a: A, i: number) => Effect) { return Effect.forEachWithIndex(f)(as) } /** * @tsplus fluent ReadonlyArray forEachEffectParWithIndex * @tsplus fluent Array forEachEffectParWithIndex * @tsplus fluent fp-ts/data/Chunk forEachEffectParWithIndex * @tsplus fluent ets/Set forEachEffectParWithIndex */ export function ext_forEachParWithIndex(as: Iterable, f: (a: A, i: number) => Effect) { return Effect.forEachParWithIndex(f)(as) } /** * @tsplus getter Iterable toChunk * @tsplus getter Iterator toChunk * @tsplus getter Generator toChunk */ export const ext_itToChunk = Chunk.fromIterable