Last active
March 8, 2017 07:42
-
-
Save zabirauf/b7ef4fd7f460514c1ac31f65ab075d4d to your computer and use it in GitHub Desktop.
And example for FunctionBinder class
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
interface CurriedFunction2<T1, T2, R> { | |
(t1: T1): (t2: T2) => R; | |
(t1: T1, t2?: T2): R; | |
} | |
interface CurriedFunction3<T1, T2, T3, R> { | |
(t1: T1): CurriedFunction2<T2, T3, R>; | |
(t1: T1, t2?: T2): (t3: T3) => R; | |
(t1: T1, t2?: T2, t3?: T3): R; | |
} | |
interface CurriedFunction4<T1, T2, T3, T4, R> { | |
(t1: T1): CurriedFunction3<T2, T3, T4, R>; | |
(t1: T1, t2?: T2): CurriedFunction2<T3, T4, R>; | |
(t1: T1, t2?: T2, t3?: T3): (t4: T4) => R; | |
(t1: T1, t2?: T2, t3?: T3, t4?: T4): R; | |
} | |
type CurriedFunction<T1, T2, T3, T4, R> = (t1: CurriedFunction<T1, T2, T3, T4, R>| T1, t2?: T2, t3?: T3, t4?: T4) => CurriedFunction<T1, T2, T3, T4, R> | | |
CurriedFunction2<T1, T2, R> | | |
CurriedFunction3<T1, T2, T3, R> | | |
CurriedFunction4<T1, T2, T3, T4, R> | R; | |
function curry2<T1, T2, T3, T4, R>(f: (t1: T1, t2?: T2, t3?: T3, t4?: T4) => R): CurriedFunction2<T1, T2, R> { | |
function curriedFunction(t1: T1): (t2: T2) => R; | |
function curriedFunction(t1: T1, t2?: T2): R; | |
function curriedFunction(t1: T1, t2?: T2): any { | |
switch (arguments.length) { | |
case 1: | |
return function(t2: T2): R { | |
return f(t1, t2); | |
} | |
case 2: | |
return f(t1, t2); | |
} | |
} | |
return curriedFunction; | |
} | |
function curry3<T1, T2, T3, T4, R>(f: (t1: T1, t2?: T2, t3?: T3, t4?: T4) => R): CurriedFunction3<T1, T2, T3, R> { | |
function curriedFunction(t1: T1): CurriedFunction2<T2, T3, R>; | |
function curriedFunction(t1: T1, t2?: T2): (t3: T3) => R; | |
function curriedFunction(t1: T1, t2?: T2, t3?: T3): R; | |
function curriedFunction(t1: T1, t2?: T2, t3?: T3): any { | |
switch (arguments.length) { | |
case 1: | |
return curry2(function(t2: T2, t3?: T3): R { | |
return f(t1, t2, t3); | |
}); | |
case 2: | |
return function(t3: T3): R { | |
return f(t1, t2, t3); | |
}; | |
case 3: | |
return f(t1, t2, t3); | |
} | |
} | |
return curriedFunction; | |
} | |
function curry4<T1, T2, T3, T4, R>(f: (t1: T1, t2?: T2, t3?: T3, t4?: T4) => R): CurriedFunction4<T1, T2, T3, T4, R> { | |
function curriedFunction(t1: T1): CurriedFunction3<T2, T3, T4, R>; | |
function curriedFunction(t1: T1, t2: T2): CurriedFunction2<T3, T4, R>; | |
function curriedFunction(t1: T1, t2: T2, t3: T3): (t4: T4) => R; | |
function curriedFunction(t1: T1, t2: T2, t3: T3, t4: T4): R; | |
function curriedFunction(t1: T1, t2?: T2, t3?: T3, t4?: T4): any { | |
switch (arguments.length) { | |
case 1: | |
return curry3(function(t2: T2, t3?: T3, t4?: T4): R { | |
return f(t1, t2, t3, t4); | |
}); | |
case 2: | |
return curry2(function(t3: T3, t4?: T4): R { | |
return f(t1, t2, t3, t4); | |
}); | |
case 3: | |
return function(t4: T4): R { | |
return f(t1, t2, t3, t4); | |
}; | |
case 4: | |
return f(t1, t2, t3, t4); | |
} | |
} | |
return curriedFunction; | |
} | |
function curry<T1, T2, T3, T4, R>(f: CurriedFunction<T1, T2, T3, T4, R>): CurriedFunction4<T1, T2, T3, T4, R>; | |
function curry<T1, T2, T3, T4, R>(f: CurriedFunction<T1, T2, T3, T4, R>): CurriedFunction3<T1, T2, T3, R>; | |
function curry<T1, T2, T3, T4, R>(f: CurriedFunction<T1, T2, T3, T4, R>): CurriedFunction2<T1, T2, R>; | |
function curry<T1, T2, T3, T4, R>(f: CurriedFunction<T1, T2, T3, T4, R>): (t1: T1, t2?: T2, t3?: T3, t4?:T4) => R; | |
function curry<T1, T2, T3, T4, R>(f: CurriedFunction<T1, T2, T3, T4, R>): CurriedFunction<T1, T2, T3, T4, R> { | |
function countArgs(func : string): number { | |
const args = func.substring(func.indexOf('(') + 1, func.indexOf(')')); | |
if (args.trim().length === 0) { | |
return 0; | |
} | |
let pos = 0; | |
let cnt = 0; | |
while (pos >= 0) { | |
cnt++; | |
pos = args.indexOf(',', pos + 1); | |
} | |
return cnt; | |
} | |
switch (countArgs(f.toString())) { | |
case 0: | |
return f; | |
case 1: | |
return f; | |
case 2: | |
return curry2(f); | |
case 3: | |
return curry3(f); | |
case 4: | |
return curry4(f); | |
default: | |
throw new SyntaxError(`More than 4 args in ${f.toString()}`); | |
} | |
} | |
interface FunctionBinderProps { | |
[key: string]: [Function, [any]] | |
} | |
class Component<T> { | |
protected props: T | |
constructor(t: T) { | |
this.props = t; | |
} | |
} | |
class FunctionBinder extends Component<FunctionBinderProps> { | |
private boundFuncs: {[key: string]: Function} | |
constructor(t: FunctionBinderProps) { | |
super(t); | |
this.bindFunctions(); | |
} | |
getFunctions() { | |
return this.boundFuncs; | |
} | |
private schonfinkelize(fn) { | |
const slice = Array.prototype.slice; | |
const stored_args = slice.call(arguments, 1); | |
return function () { | |
const new_args = slice.call(arguments), | |
args = stored_args.concat(new_args); | |
return fn.apply(null, args); | |
}; | |
} | |
private bindFunctions() { | |
const newFuncs = {}; | |
for (let name in this.props) { | |
const p = this.props[name]; | |
newFuncs[name] = curry(p[0].bind(null, ...p[1])); | |
} | |
this.boundFuncs = newFuncs; | |
} | |
} | |
const addVal = 9; | |
const sel = this; | |
const f = new FunctionBinder({ | |
deleteHandler: [ | |
((id: number) => id + this.addVal).bind(sel), | |
[1] | |
], | |
clickHandler: [ | |
((a: number, b: number) => a + b), | |
[1, 4] | |
], | |
testHandler: [ | |
((a: number, b:number) => a + b), | |
[2] | |
], | |
add4: [ | |
((a: number, b: number, c: number, d: string) => `${d} -> ${a + b + c}`), | |
[100,200] | |
] | |
}); | |
console.log(f); | |
const {deleteHandler, clickHandler, testHandler, add4} = f.getFunctions(); | |
console.log(deleteHandler()); | |
console.log(clickHandler()); | |
console.log(testHandler(11)); | |
console.log(add4(30, 'Hello')); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment