tiinvo
Version:
A library of types and utilities for your TypeScript and JavaScript projects
393 lines (392 loc) • 9.71 kB
JavaScript
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