UNPKG

tiinvo

Version:

A library of types and utilities for your TypeScript and JavaScript projects

393 lines (392 loc) 9.71 kB
import * as Sequence from './Sequence.js'; const guardsymbol = Symbol('sequence.guard'); export function make(g, ...values) { if (typeof g === 'function' || ('guard' in g && typeof g.guard === 'function')) { const _t = Sequence.make.apply(null, values); if (typeof g === 'function') { if (values.every(g)) { _t[guardsymbol] = g; return _t; } } else { if (values.every(g.guard)) { _t[guardsymbol] = g.guard; return _t; } } throw new TypeError("Non homogeneous arguments"); } else { throw new TypeError("Invalid guard argument, must be a Guardable or GuardableModule functor"); } } //#endregion //#region guards /** * Checks if the parameter `x` is a `TypedSequence.t<unknown>` * * @example * * ```ts * import { TypedSequence, Sequence, Num } from 'tiinvo' * * const a = TypedSequence.make(Num) * const b = Sequence.make() * * TypedSequence.guard(a) // true * TypedSequence.guard(b) // false * ``` * * @param x the guarded value * @returns * - true if x is a TypedSequence * - false otherwise * @group Guardables * @since 4.0.0 */ export const guard = (x) => Sequence.guard(x) && guardsymbol in x; export function append(a, b) { if (guard(a) && arguments.length === 2) { const p = [{ guard: a[guardsymbol] }, ...a, b]; return make.apply(null, p); } return (b) => { const p = [{ guard: b[guardsymbol] }, ...b, a]; return make.apply(null, p); }; } export function concat(a, b) { if (guard(a) && guard(b)) { return make.apply(null, [{ guard: a[guardsymbol] }, ...a, ...b]); } return (b) => make.apply(null, [{ guard: b[guardsymbol] }, ...b, ...a]); } export function prepend(a, b) { if (guard(a)) { const x = [{ guard: a[guardsymbol] }, b, ...a]; return make.apply(null, x); } return (b) => { const p = [{ guard: b[guardsymbol] }, a, ...b]; return make.apply(null, p); }; } export function sort(a, mod) { const getcmp = (x) => typeof x === 'function' ? x : x.cmp; if (arguments.length === 2 && guard(a)) { const p = [{ guard: a[guardsymbol] }, ...Array.from(a).sort(getcmp(mod))]; return make.apply(null, p); } return (x) => { const p = [{ guard: x[guardsymbol] }, ...Array.from(x).sort(getcmp(a))]; return make.apply(null, p); }; } //#endregion //#region accessors /** * Counts the number of elements that satisfy a given predicate * * @example * * ```ts * import { TypedSequence, Num } from 'tiinvo' * * const s = TypedSequence.make(Num, 10, 20, 30) * * TypedSequence.count(s, Num.gt(10)) // 2 * TypedSequence.count(Num.gt(10))(s) // 2 * ``` * * @param a the sequence * @returns the counted elements * @since 4.0.0 */ export const count = Sequence.count; /** * * * @example * * ```ts * import { TypedSequence, Str } from 'tiinvo' * * const s = TypedSequence.make(Str, 'hello', 'world') * * TypedSequence.get(s, 0) // 'hello' * TypedSequence.get(s, 9) // throws RangeError * ``` * * @since 4.0.0 */ export const get = Sequence.get; /** * Gets the first element of a TypedSequence. * * Returns `Option.None` if none is found. * * @example * * ```ts * import { TypedSequence, Num } from 'tiinvo' * * const s0 = TypedSequence.make(Num, 10, 20, 30) * const s1 = TypedSequence.make(Num) * * TypedSequence.first(s0) // 10 * TypedSequence.first(s1) // null * ``` * * @since 4.0.0 */ export const first = Sequence.first; /** * Gets a Sequence.t<A>'s last element. * * Returns `Option.None` if none is found. * * @example * * ```ts * import { TypedSequence, Num } from 'tiinvo' * * const s0 = TypedSequence.make(Num, 10, 20, 30) * const s1 = TypedSequence.make(Num) * * TypedSequence.last(s0) // 30 * TypedSequence.last(s1) // null * ``` * ``` * * @since 4.0.0 */ export const last = Sequence.last; /** * Gets the length of a `TypedSequence.t<A>` * * @example * * ```ts * import { TypedSequence, Num } from 'tiinvo' * * const s = TypedSequence.make(Num, 1, 2, 3) * * TypedSequence.length(s) // 3 * ``` * * @since 4.0.0 */ export const length = Sequence.length; /** * Gets values of a `TypedSequence.t<A>` as an immutable indexed object. * * @example * * ```ts * import { TypedSequence, Str } from 'tiinvo' * * const s = TypedSequence.make(Str, 'hello', 'world') * * TypedSequence.values(s) // { 0: 'hello', 1: 'world' } * ``` * * @since 4.0.0 */ export const values = Sequence.values; export function cmp(cmp, a, b) { const cmpfn = typeof cmp === 'function' ? cmp : cmp.cmp; if (cmpfn === undefined) { throw new TypeError('Invalid Comparable<A> or ComparableModule<A> functor'); } if (a && b && (!guard(a) || !guard(b))) { throw new TypeError('Cannot compare TypedSequence A and B of different types'); } if (guard(a) && guard(b)) { if (a[guardsymbol] !== b[guardsymbol]) { throw new TypeError('Cannot compare TypedSequence A and B of different types'); } return Sequence.cmp(cmpfn, a, b); } else if (guard(a)) { return (b) => { if (guard(b) && a[guardsymbol] === b[guardsymbol]) { return Sequence.cmp(cmpfn, a, b); } throw new TypeError('Cannot compare TypedSequence A and B of different types'); }; } else { return (a, b) => { if (guard(a) && guard(b) && a[guardsymbol] === b[guardsymbol]) { return Sequence.cmp(cmpfn, a, b); } throw new TypeError('Cannot compare TypedSequence A and B of different types'); }; } } export function eq(eq, a, b) { const eqfn = typeof eq === 'function' ? eq : eq.eq; if (eqfn === undefined) { throw new TypeError('Invalid Equatable<A> or EquatableModule<A> functor'); } if (a && b && (!guard(a) || !guard(b))) { throw new TypeError('Cannot compare TypedSequence A and B of different types'); } if (guard(a) && guard(b)) { if (a[guardsymbol] !== b[guardsymbol]) { throw new TypeError('Cannot compare sequences of different types'); } return Sequence.eq(eqfn, a, b); } else if (guard(a)) { return (b) => { if (guard(b) && a[guardsymbol] === b[guardsymbol]) { return Sequence.eq(eqfn, a, b); } throw new TypeError('Cannot compare sequences of different types'); }; } else { return (a, b) => { if (guard(a) && guard(b) && a[guardsymbol] === b[guardsymbol]) { return Sequence.eq(eqfn, a, b); } throw new TypeError('Cannot compare sequences of different types'); }; } } //#endregion //#region predicates /** * Returns `true` if the sorted list is empty. * * @example * * ```ts * import { TypedSequence, Num } from 'tiinvo' * * const s = TypedSequence.make(Num) * const s1 = TypedSequence.make(Num, 10) * * TypedSequence.empty(s) // true * TypedSequence.empty(s1) // false * ``` * * @since 4.0.0 */ export const empty = Sequence.empty; /** * Returns `true` if the sorted list is populated. * * @example * * ```ts * import { TypedSequence, Num } from 'tiinvo' * * const s = TypedSequence.make(Num, 10, 20, 30) * * TypedSequence.populated(s) // true * TypedSequence.populated(TypedSequence.make(Num)) // false * ``` * * @since 4.0.0 */ export const populated = Sequence.populated; //#endregion //#region serializables /** * Converts a `TypedSequence.t<A>` to an array of `a[]` * * @example * * ```ts * import { TypedSequence, Num } from 'tiinvo' * * const sl = TypedSequence.make(Num, 3, 2, 1) * * TypedSequence.toArray(sl) // [3, 2, 1] * ``` * * @param a the TypedSequence * @returns the array * @group Serializables * @since 4.0.0 */ export const toArray = Sequence.toArray; /** * Converts a `TypedSequence.t<A>` to a jsonizable value * * @example * * ```ts * import { TypedSequence, Num } from 'tiinvo' * * const sl = TypedSequence.make(Num, 3, 2, 1) * * TypedSequence.toJSON(sl) // [3, 2, 1] * ``` * * @param a the TypedSequence * @returns the JSON * @group Serializables * @since 4.0.0 */ export const toJSON = Sequence.toJSON; /** * Converts a `TypedSequence.t<A>` to a set of `Set<A>` * * @example * * ```ts * import { TypedSequence, Num } from 'tiinvo' * * const sl = TypedSequence.make(Num, 3, 2, 1) * * TypedSequence.toMap(sl) // Map([0, 3], [1, 2], [2, 1]) * ``` * * @param a the TypedSequence * @returns the Map * @group Serializables * @since 4.0.0 */ export const toMap = Sequence.toMap; /** * Converts a `TypedSequence.t<A>` to a set of `Set<A>` * * @example * * ```ts * import { TypedSequence, Num } from 'tiinvo' * * const sl = TypedSequence.make(Num, 3, 2, 1) * * TypedSequence.toSet(sl) // Set(3, 2, 1) * ``` * * @param a the TypedSequence * @returns the Set * @group Serializables * @since 4.0.0 */ export const toSet = Sequence.toSet; /** * Converts a `TypedSequence.t<A>` to a string * * @example * * ```ts * import { TypedSequence, Num } from 'tiinvo' * * const sl = TypedSequence.make(Num, 3, 2, 1) * * TypedSequence.toString(sl) // "3,2,1" * ``` * * @param a the TypedSequence * @group Serializables * @since 4.0.0 */ export const toString = Sequence.toString; //#endregion