/** @module flow.ts */ import { complement } from './function/complement' import { curry } from './function/curry' import { untypedCurry } from './function/untypedCurry' import { Function1, Function2, FunctionV, Predicate } from './helper-types' import { trace } from './logging' import { Maybe } from './maybe' export function when( pred: Function1, whenTrueFn: Function1, input: A ): A | B export function when( pred: Function1, whenTrueFn: Function1 ): ( input: A ) => A | B export function when( pred: Function1 ): ( whenTrueFn: Function1 ) => ( input: A2 ) => A2|B /** * Takes a predicate, a function, and a value. If pred(a) is true then will run function over value otherwise returns value. * :: pred -> fn -> x -> x | fn(x) */ export function when( ...args ) { return untypedCurry( ( pred, whenTrueFn, x ) => pred( x ) === true ? whenTrueFn( x ) : x )( ...args ) } export function times ( callback: Function1, repeat: number ): A[] export function times ( callback: Function1 ): ( repeat: number ) => A[] /** * Takes a callback and a repeat number n, iterates over that function n times. * :: ( fn -> n -> a ) -> n -> a[] */ export function times( ...args ) { return untypedCurry( ( callback, numberOfTimes ) => { const returnValues: any[] = [] for ( let index = 0; index < numberOfTimes; index++ ) { returnValues.push( callback( index ) ) } return returnValues } )( ...args ) } export function times_( repeat: number, callback: Function1 ): A[] export function times_( repeat: number ): ( callback: Function1 ) => A[ ] /** * Takes a callback and a repeat number n, iterates over that function n times. * :: ( fn -> n -> a ) -> n -> a[] */ export function times_( ...args ) { return untypedCurry( ( numberOfTimes, callback ) => { const returnValues: any[] = [] for ( let index = 0; index < numberOfTimes; index++ ) { returnValues.push( callback( index ) ) } return returnValues } )( ...args ) } export function timesWithRepeat ( callback: Function2, repeat: number ): A[] export function timesWithRepeat( callback: Function2 ): ( repeat: number ) => A[] /** * Takes a callback and a repeat number n, iterates over that function n times. * :: ( fn -> n -> nt -> a ) -> nt -> a[] */ export function timesWithRepeat( ...args ) { return untypedCurry( ( callback, numberOfTimes ) => { const returnValues: any[] = [] for ( let index = 0; index < numberOfTimes; index++ ) { returnValues.push( callback( index, numberOfTimes ) ) } return returnValues } )( ...args ) } export function timesWithRepeat_( repeat: number, callback: Function2 ): A[] export function timesWithRepeat_( repeat: number ): ( callback: Function2 ) => A[] /** * Takes a callback and a repeat number n, iterates over that function n times. * :: ( fn -> n -> nt -> a ) -> nt -> a[] */ export function timesWithRepeat_( ...args ) { return untypedCurry( ( numberOfTimes, callback ) => { const returnValues: any[] = [] for ( let index = 0; index < numberOfTimes; index++ ) { returnValues.push( callback( index, numberOfTimes ) ) } return returnValues } )( ...args ) } /** * Alias to for `times` * :: ( fn -> a ) -> n -> a[] */ export const loop = times export function tryCatch ( failCallback: Function1, testCallback: FunctionV<( null|undefined ), A> ): A export function tryCatch ( failCallback: Function1 ): ( testCallback: FunctionV<( null|undefined ), A> ) => A /** * Takes failure callback f and test function t, runs t or f if t failes. * :: ( f -> e -> a ) -> ( f -> a) -> a */ export function tryCatch( ...args ) { return untypedCurry( ( failCallback, testCallback ) => { try { return testCallback() } catch ( e ) { return failCallback( e ) } } ) } export function tryCatchWithParams ( failCallback: Function1, testCallback: FunctionV ): ( ...args: B[] ) => A export function tryCatchWithParams ( failCallback: Function1 ): ( testCallback: FunctionV ) => ( ...args: B[] ) => A /** * Like tryCatch only test function receives arguments in a seperate callback * :: ( f -> e -> a ) -> ( f -> a) -> a */ export function tryCatchWithParams( failCallback, testCallback? ) { const doIt = ( _testCallback ) => ( ...args ) => { try { return _testCallback( ...args ) } catch ( e ) { return failCallback( e ) } } if ( !testCallback ) { return doIt } else { return doIt( testCallback ) } } /** * Takes a value v, a glob of predicates, and a test a parameter "a", returns true if any predicate given "a" matches "v" * :: v -> ...((a) -> bool) -> a -> bool */ export const logical = ( value: boolean ) => ( ...fns: Array> ) => ( x: A ) => { for ( const fn of fns ) { if ( fn( x ) === value ) { return true } } return false } /** * Takes a glob of predicates "p" taking a value "a", then a value "a" and returns true if any of "p" given "a" is true * :: v -> ...((a) -> bool) -> a -> bool */ export const either = logical( true ) /** * Takes a glob of predicates "p" taking a value "a", then a value "a" and returns true if all of "p" given "a" is true * :: v -> ...((a) -> bool) -> a -> bool */ export const and = ( ...fns: Array> ) => complement( logical( true )( ...fns ) ) /* 900 */ /** * ifElse */ const _ifElse = untypedCurry( ( predicate, trueCondition, falseCondition, input ) => predicate( input ) ? trueCondition( input ) : falseCondition( input ), ) export function ifElse( p: Function1, t: Function1, f: Function1, i: A ): B export function ifElse( p: Function1, t: Function1, f: Function1 ): ( i: A ) => B export function ifElse( p: Function1 ): ( t: Function1 ) => ( f: Function1 ) => ( i: A3 ) => B2 /** * Functional If/Else branching * Given predicate(input), execute trueCondition(input) or falseCondition(input). * * @example * * // remove lines starting with comments * ifElse( test( /^\#/ ) , _ => '' , identity ) * * :: predicate ( input A -> boolean ) -> * trueCondition ( input A -> output1 B) -> * falseCondition ( input A -> output2 B)-> * input -> * output B */ export function ifElse( ...args ) { return _ifElse( ...args ) } export function gt( a: number ): ( b: number ) => boolean export function gt( a: number, b: number ): boolean /** * Predicate, right associative greater-than. Check that the second parameter is greater-than the first * @param a number which `b` must be greater-than * @param b number which is checked to be greater-than `a` * @example * pipeline( * 10, * gt(11) * ) // false */ export function gt( ...args ) { return untypedCurry( ( a, b ) => b > a )( ...args ) } export function gte( a: number ): ( b: number ) => boolean export function gte( a: number, b: number ): boolean /** * Predicate, right associative greater-than or equal to. Check that the second parameter is greater-than or equal to the first * @param a number which `b` must be greater than * @param b number which is checked to be greater than `a` * @example * pipeline( * 10, * gt(11) * ) // false */ export function gte( ...args ) { return untypedCurry( ( a, b ) => b >= a )( ...args ) } export function lt( a: number ): ( b: number ) => boolean export function lt( a: number, b: number ): boolean /** * Predicate, right associative less-than. Check that the second parameter is less-than the first * @param a number which `b` must be less-than * @param b number which is checked to be less-than `a` * @example * pipeline( * 10, * gt(11) * ) // false */ export function lt( ...args ) { return untypedCurry( ( a, b ) => b < a )( ...args ) } export function lte( a: number ): ( b: number ) => boolean export function lte( a: number, b: number ): boolean /** * Predicate, right associative less-than or equal to. Check that the second parameter is less-than or equal to the first * @param a number which `b` must be less-than * @param b number which is checked to be less-than `a` * @example * pipeline( * 10, * gt(11) * ) // false */ export function lte( ...args ) { return untypedCurry( ( a, b ) => b <= a )( ...args ) } export function eq( a: T ): ( b: T ) => boolean export function eq( a: T, b: T ): boolean /** * Predicate checks that both given values `a` and `b` are the same. Strictly typed */ export function eq( ...args ) { return untypedCurry( ( a, b ) => b === a )( ...args ) } export function untypedEq( a: any ): ( b: any ) => boolean export function untypedEq( a: any, b: any ): boolean /** * Predicate checks that both given values `a` and `b` are the same. Untyped. */ export function untypedEq( ...args ) { return untypedCurry( ( a, b ) => b === a )( ...args ) }