Skip to content

Instantly share code, notes, and snippets.

@zabirauf
Last active March 8, 2017 07:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zabirauf/b7ef4fd7f460514c1ac31f65ab075d4d to your computer and use it in GitHub Desktop.
Save zabirauf/b7ef4fd7f460514c1ac31f65ab075d4d to your computer and use it in GitHub Desktop.
And example for FunctionBinder class
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