import { AnyArgs } from "./internal_types" import { AnyFunc } from "./types" export type Placeholder = symbol export const __: Placeholder = Symbol('Placeholder') const countArgs = (s: AnyArgs) => { let i = 0 for (const v of s) v!==__ && i++ return i } // TODO: try to make it mutable. // { 0: __, 1: 10 }, [ 11 ] const addArgs = (args: AnyArgs, _args: AnyArgs) => { const len = args.length const new_args = args.slice() const _args_len = _args.length let _args_left = _args_len let i=0 for (; _args_left && i { const args2add = fn.length - args.length - countArgs(new_args) if(args2add < 1) { return fn(...addArgs(args, new_args)) } else { const curried = (...__args: AnyArgs) => _curry( fn, addArgs(args, new_args), __args ) ;(curried as any).$args_left = args2add return curried } } export const curry = (fn: AnyFunc) => ( (...args: AnyArgs) => fn.length>countArgs(args) ? _curry(fn, [], args) : fn(...args) ) const endlessph = (fn: Func) => { type ReturnT = ReturnType type p0 = Parameters[0] function _endlessph(a: p0): ReturnT function _endlessph(a: Placeholder): Func function _endlessph(a: p0 | Placeholder) { return a===__ ? fn : fn(a) } return _endlessph } export type Curried2 = { (a: Placeholder, b: p1): (a: p0) => ReturnT (a: p0, b: Placeholder): (b: p1) => ReturnT (a: p0): (b: p1) => ReturnT (a: p0, b: p1): ReturnT } type Func2 = (a: any, b: any) => any const zero = 0 export function curry2(fn: Func) { type p0 = Parameters[0] type p1 = Parameters[1] type ReturnT = ReturnType function curried2(a: Placeholder, b: p1): (a: p0) => ReturnT function curried2(a: p0, b: Placeholder): (b: p1) => ReturnT function curried2(a: p0 ): (b: p1) => ReturnT function curried2(a: p0, b: p1): ReturnT function curried2(a: p0 | Placeholder, ...args: [b?: p1]) { return args.length>zero ? a===__ ? endlessph((a: p0) => fn(a, args[zero]) as ReturnType) : fn(a, args[zero]) as ReturnType : (b: p1) => fn(a, b) as Curried2 } return curried2 } type Func3 = (a: any, b: any, c: any) => any export function curry3(fn: Func) { // type p0 = Parameters[0] // type p1 = Parameters[1] // type p2 = Parameters[2] // type ReturnT = ReturnType // TODO: optimize. // Cannot use ts-toolbelt due to this error: // Excessive stack depth comparing types 'GapsOf' and 'GapsOf' return curry(fn) }