import { Equaler , Comparer } from "@esfx/equatable" ; /**
 * Throws the provided value.
 */ export function fail ( value ) { throw value ; } /**
 * Does nothing.
 */ export function noop ( ... args ) ; export function noop ( ) { } /**
 * Returns the provided value.
 */ export function identity < T > ( value ) { return value ; } /**
 * A function that always returns `true`.
 */ export function alwaysTrue ( ) { return true ; } export { alwaysTrue as T } ; /**
 * A function that always returns `false`.
 */ export function alwaysFalse ( ) { return false ; } export { alwaysFalse as F } ; /**
 * Returns a function that always throws the provided error.
 */ export function alwaysFail ( error ) { return ( ) => fail ( error ) ; } /**
 * Returns a function that returns the provided value.
 */ export function always < T > ( value ) { return ( ) => value ; } export declare namespace always { export { alwaysTrue as true , alwaysFalse as false , alwaysFail as fail } ; } internal export namespace always { always . true = alwaysTrue ; always . false = alwaysFalse ; always . fail = alwaysFail ; } /**
 * Returns a function that produces a monotonically increasing number value each time it is called.
 */ export function incrementer ( start = 0 ) { return ( ) => start ++ ; } export namespace incrementer { /**
     * Returns a function that produces a monotonically increasing number value each time it is called.
     */ export function step ( count , start = 0 ) { return count > 0 ? ( ( ) => start += count ) : fail ( new Error ( "Count must be a positive number" ) ) ; } } /**
 * Returns a function that produces a monotonically increasing number value each time it is called.
 */ export function decrementer ( start = 0 ) { return ( ) => start -- ; } export namespace decrementer { /**
     * Returns a function that produces a monotonically decreasing number value each time it is called.
     */ export function step ( count , start = 0 ) { return count > 0 ? ( ( ) => start -= count ) : fail ( new Error ( "Count must be a positive number" ) ) ; } } /**
 * Makes a "tuple" from the provided arguments.
 */ export function tuple < A extends readonly [ unknown ? , ... unknown [ ] ] > ( ... args ) { return args ; } /**
 * Truncates a function's arguments to a fixed length.
 */ export function nAry < T , R > ( f , length ) ; export function nAry < T , A , R > ( f , length ) ; export function nAry < T , A , B , R > ( f , length ) ; export function nAry < T , A , B , C , R > ( f , length ) ; export function nAry < T , A , B , C , D , R > ( f , length ) ; export function nAry < T , A , R > ( f , length ) { return function ( ... args ) { return f . call ( this , ... args . slice ( 0 , length ) ) ; } ; } /**
 * Right-to-left composition of functions (i.e. `compose(g, f)` is `x => g(f(x))`).
 */ export function compose < A extends unknown [ ] , B , C > ( fb , fa ) ; export function compose < A extends unknown [ ] , B , C , D > ( fc , fb , fa ) ; export function compose < A extends unknown [ ] , B , C , D , E > ( fd , fc , fb , fa ) ; export function compose < A extends unknown [ ] , B , C , D , E , F > ( fe , fd , fc , fb , fa ) ; export function compose < T > ( ... rest ) ; export function compose < T > ( ... rest ) { const last = rest . pop ( ) ! ; return ( ... args ) => rest . reduceRight ( ( a , f ) => f ( a ) , last ( ... args ) ) ; } /**
 * Left-to-right composition of functions (i.e. `pipe(g, f)` is `x => f(g(x))`).
 */ export function pipe < A extends unknown [ ] , B , C > ( fa , fb ) ; export function pipe < A extends unknown [ ] , B , C , D > ( fa , fb , fc ) ; export function pipe < A extends unknown [ ] , B , C , D , E > ( fa , fb , fc , fd ) ; export function pipe < A extends unknown [ ] , B , C , D , E , F > ( fa , fb , fc , fd , fe ) ; export function pipe < A extends unknown [ ] , B > ( first , ... rest ) ; export function pipe < A extends unknown [ ] , B > ( first , ... rest ) { return ( ... args ) => rest . reduce ( ( a , f ) => f ( a ) , first ( ... args ) ) ; } param key export function property < K extends PropertyKey > ( key ) { return object => object [ key ] ; } param key export function propertyWriter < K extends PropertyKey > ( key ) { return ( object , value ) => { object [ key ] = value ; } ; } /**
 * Returns a function that invokes a method on the object provided as the function's first argument.
 *
 * ```ts
 * const fn = invoker("sayHello", "Bob");
 * fn({ sayHello(name) { console.log(`Hello, ${name}!`); } }); // prints: "Hello, Bob!"
 * ```
 */ export function invoker < K extends PropertyKey > ( key ) ; export function invoker < K extends PropertyKey , A0 > ( key , a0 ) ; export function invoker < K extends PropertyKey , A0 , A1 > ( key , a0 , a1 ) ; export function invoker < K extends PropertyKey , A0 , A1 , A2 > ( key , a0 , a1 , a2 ) ; export function invoker < K extends PropertyKey , A0 , A1 , A2 , A3 > ( key , a0 , a1 , a2 , a3 ) ; export function invoker < K extends PropertyKey , A extends unknown [ ] > ( key , ... args ) ; export function invoker < K extends PropertyKey , AX > ( key , ... args ) ; export function invoker < K extends PropertyKey , AX > ( key , ... args ) { return ( object , ... rest ) => object [ key ] ( ... args , ... rest ) ; } /**
 * Returns a function that calls the function provided as its first argument.
 *
 * ```ts
 * const fn = caller(1, 2);
 * fn((a, b) => a + b); // 3
 * ```
 */ export function caller ( ) ; export function caller < A0 > ( a0 ) ; export function caller < A0 , A1 > ( a0 , a1 ) ; export function caller < A0 , A1 , A2 > ( a0 , a1 , a2 ) ; export function caller < A0 , A1 , A2 , A3 > ( a0 , a1 , a2 , a3 ) ; export function caller < A extends unknown [ ] > ( ... args ) ; export function caller < AX > ( ... args ) ; export function caller < AX > ( ... args ) { return ( func , ... rest ) => func ( ... args , ... rest ) ; } /**
 * Returns a function that constructs an instance from a constructor provided as its first argument.
 *
 * ```ts
 * const fn = allocator("Bob");
 * class Person {
 *   constructor(name) { this.name = name; }
 * }
 * class Dog {
 *   constructor(owner) { this.owner = owner; }
 * }
 * fn(Person).name; // "Bob"
 * fn(Dog).owner; // "Bob"
 * ```
 */ export function allocator ( ) ; export function allocator < A0 > ( a0 ) ; export function allocator < A0 , A1 > ( a0 , a1 ) ; export function allocator < A0 , A1 , A2 > ( a0 , a1 , a2 ) ; export function allocator < A0 , A1 , A2 , A3 > ( a0 , a1 , a2 , a3 ) ; export function allocator < A extends unknown [ ] > ( ... args ) ; export function allocator < AX > ( ... args ) ; export function allocator < AX > ( ... args ) { return ( ctor , ... rest ) => new ctor ( ... args , ... rest ) ; } /**
 * Returns a function that constructs an instance of the provided constructor.
 *
 * ```ts
 * class Point {
 *   constructor(x, y) {
 *     this.x = x;
 *     this.y = y;
 *   }
 * }
 * const fn = factory(Point);
 * fn(1, 2); // Point { x: 1, y: 2 }
 * fn(3, 4); // Point { x: 3, y: 4 }
 * ```
 */ export function factory < A extends unknown [ ] , R > ( ctor ) ; export function factory < A0 , A extends unknown [ ] , R > ( ctor , a0 ) ; export function factory < A0 , A1 , A extends unknown [ ] , R > ( ctor , a0 , a1 ) ; export function factory < A0 , A1 , A2 , A extends unknown [ ] , R > ( ctor , a0 , a1 , a2 ) ; export function factory < A0 , A1 , A2 , A3 , A extends unknown [ ] , R > ( ctor , a0 , a1 , a2 , a3 ) ; export function factory < A extends unknown [ ] , R > ( ctor , ... args ) ; export function factory < AX , R > ( ctor , ... args ) ; export function factory < AX , R > ( ctor , ... args ) { return ( ... rest ) => new ctor ( ... args , ... rest ) ; } /**
 * Returns a function that calls the provided function, but swaps the first and second arguments.
 *
 * ```ts
 * function compareNumbers(a, b) { return a - b };
 * [3, 1, 2].sort(compareNumbers); // [1, 2, 3]
 * [3, 1, 2].sort(flip(compareNumbers)); // [3, 2, 1]
 * ```
 */ export function flip < A , B , C extends unknown [ ] , R > ( f ) { return ( b , a , ... c ) => f ( a , b , ... c ) ; } function recursiveLazy ( ) { throw new Error ( "Lazy factory recursively references itself during its own evaluation." ) ; } /**
 * Returns a function that will evaluate once when called will subsequently always return the same result.
 *
 * ```ts
 * let count = 0;
 * const fn = lazy(() => count++);
 * fn(); // 0
 * fn(); // 0
 * count; // 1
 * ```
 */ export function lazy < T , A extends unknown [ ] > ( factory , ... args ) { let f = ( ) : T => { f = recursiveLazy ; try { f = always ( factory ( ... args ) ) ; } catch ( e ) { f = alwaysFail ( e ) ; } return f ( ) ; } ; return ( ) => f ( ) ; } const uncurryThis_ = Function . prototype . bind . bind ( Function . prototype . call ) ; /**
 * Returns a function whose first argument is passed as the `this` receiver to the provided function when called.
 *
 * ```ts
 * const hasOwn = uncurryThis(Object.prototype.hasOwnProperty);
 * const obj = { x: 1 };
 * hasOwn(obj, "x"); // true
 * hasOwn(obj, "y"); // false
 * ```
 */ export function uncurryThis < T , A extends unknown [ ] , R > ( f ) { return uncurryThis_ ( f ) ; } see {@link @esfx/equatable#Equaler.defaultEqualer} export function equate < T > ( a , b ) { return Equaler . defaultEqualer . equals ( a , b ) ; } export namespace equate { /**
     * Creates a copy of `equate` for a specific `Equaler`.
     */ export function withEqualer < T > ( equaler ) { return ( a , b ) => equaler . equals ( a , b ) ; } } /**
 * Generates a hashcode from a value.
 */ export function hash ( value ) { return Equaler . defaultEqualer . hash ( value ) ; } export namespace hash { /**
     * Creates a copy of `hash` for a specific `Equaler`.
     */ export function withEqualer < T > ( equaler ) { return value => equaler . hash ( value ) ; } } see {@link @esfx/equatable#Comparer.defaultComparer} export function compare < T > ( a , b ) { return Comparer . defaultComparer . compare ( a , b ) ; } export namespace compare { /**
     * Creates a copy of `compare` for a specific `Comparer`.
     */ export function withComparer < T > ( comparer ) { return ( a , b ) => comparer . compare ( a , b ) ; } } /**
 * Clamps a value to a set range using the default `Comparer`.
 *
 * ```ts
 * const fn = clamp(0, 10);
 * fn(-1); // 0
 * fn(15); // 10
 * fn(7); // 7
 * ```
 */ export function clamp < T > ( min , max ) { return value => Comparer . defaultComparer . compare ( value , min ) < 0 ? min : Comparer . defaultComparer . compare ( value , max ) > 0 ? max : value ; } export namespace clamp { /**
     * Creates a copy of `clamp` for a specific `Comparer`.
     */ export function withComparer < T > ( comparer ) { return ( min , max ) => ( value ) => comparer . compare ( value , min ) < 0 ? min : comparer . compare ( value , max ) > 0 ? max : value ; } } /**
 * Returns a function that returns the complement of calling `f`.
 *
 * ```ts
 * alwaysTrue(); // true
 * complement(alwaysTrue)(); // false
 *
 * alwaysFalse(); // false
 * complement(alwaysFalse)(); // true
 * ```
 */ export function complement < A extends unknown [ ] > ( f ) { return ( ... args ) => ! f ( ... args ) ; } /**
 * Returns a function that returns the result of calling its first argument if that result is "falsy", otherwise returning the result of calling its second argument.
 * NOTE: This performs the same shortcutting as a logical AND (i.e. `a() && b()`)
 */ export function both < T , U extends T , V extends T > ( a , b ) ; export function both < A extends unknown [ ] , R1 , R2 > ( a , b ) ; export function both < A extends unknown [ ] , R1 , R2 > ( a , b ) { return ( ... args ) => a ( ... args ) && b ( ... args ) ; } /**
 * Returns a function that returns the result of calling its first argument if that result is "truthy", otherwise returning the result of calling its second argument.
 * NOTE: This performs the same shortcutting as a logical OR (i.e. `a() || b()`).
 */ export function either < T , U extends T , V extends T > ( a , b ) ; export function either < A extends unknown [ ] , R1 , R2 > ( a , b ) ; export function either < A extends unknown [ ] , R1 , R2 > ( a , b ) { return ( ... args ) => a ( ... args ) || b ( ... args ) ; } /**
 * Returns a function that returns the result of calling the first callback, if that result is neither `null` nor `undefined`; otherwise, returns the result of calling the second callback with the same arguments.
 * NOTE: This performs the same shortcutting as nullish-coalesce (i.e. `a() ?? b()`).
 */ export function fallback < A extends unknown [ ] , T , U > ( a , b ) { return ( ... args ) => { const result = a ( ... args ) ; return result !== null && result !== undefined ? result ! : b ( ... args ) ; } ; } /**
 * Returns `true` if a value is neither `null` nor `undefined`.
 */ export function isDefined < T > ( value ) { return value !== null && value !== undefined ; }