functionfoo (/* parameters are declared here*/) {// ...}constfoo= (/* parameters are declared here */) =>// ...constfoo=function (/* parameters are declared here */) {// ...}
consttrace= label => value => {console.log(`${ label }: ${ value }`);return value;};
现在我们可以使用这个来检查函数了:
constcompose= (...fns) => x =>fns.reduceRight((y, f) =>f(y), x);consttrace= label => value => {console.log(`${ label }: ${ value }`);return value;};constg= n => n +1;constf= n => n *2;/*Note: function application order isbottom-to-top:*/consth=compose(trace('after f'), f,trace('after g'), g);h(20);/*after g: 21after f: 42*/
constpipe= (...fns) => x =>fns.reduce((y, f) =>f(y), x);
现在我们可以用pipe把上面的重写下:
constpipe= (...fns) => x =>fns.reduce((y, f) =>f(y), x);consttrace= label => value => {console.log(`${ label }: ${ value }`);return value;};constg= n => n +1;constf= n => n *2;/*Now the function application orderruns top-to-bottom:*/consth=pipe( g,trace('after g'), f,trace('after f'),);h(20);/*after g: 21after f: 42*/
constpipe= (...fns) => x =>fns.reduce((y, f) =>f(y), x);consttrace= label => value => {console.log(`${ label }: ${ value }`);return value;};constg= n => n +1;constf= n => n *2;consth=pipe( g,trace('after g'), f,trace('after f'),);h(20);/*after g: 21after f: 42*/
constpipe= (...fns) => x =>fns.reduce((y, f) =>f(y), x);consttrace= (label, value) => {console.log(`${ label }: ${ value }`);return value;};constg= n => n +1;constf= n => n *2;consth=pipe( g,// `trace`调用不再是`point-free`风格,// 引入中间变量, `x`. x =>trace('after g', x), f, x =>trace('after f', x),);h(20);
constpipe= (...fns) => x =>fns.reduce((y, f) =>f(y), x);consttrace= value => label => {console.log(`${ label }: ${ value }`);return value;};constg= n => n +1;constf= n => n *2;consth=pipe( g,// the trace() calls can't be point-free,// because arguments are expected in the wrong order. x =>trace(x)('after g'), f, x =>trace(x)('after f'),);h(20);
如果不想这样,可以使用名为flip()的函数解决该问题,该函数只是翻转两个参数的顺序:
constflip= fn => a => b =>fn(b)(a);
现在我们可以创建一个flippedTrace函数:
constflippedTrace=flip(trace);
再这样使用这个flippedTrace:
constflip= fn => a => b =>fn(b)(a);constpipe= (...fns) => x =>fns.reduce((y, f) =>f(y), x);consttrace= value => label => {console.log(`${ label }: ${ value }`);return value;};constflippedTrace=flip(trace);constg= n => n +1;constf= n => n *2;consth=pipe( g,flippedTrace('after g'), f,flippedTrace('after f'),);h(20);
consttrace= label => value => {console.log(`${ label }: ${ value }`);return value;};consttraceAfterG=trace('after g');
等同于下面这个:
consttraceAfterG= value => {constlabel='after g';console.log(`${ label }: ${ value }`);return value;};
如果我们为traceAfterG交换trace('after g'),那就意味着同样的事情:
constpipe= (...fns) => x =>fns.reduce((y, f) =>f(y), x);consttrace= label => value => {console.log(`${ label }: ${ value }`);return value;};// The curried version of trace()// saves us from writing all this code...consttraceAfterG= value => {constlabel='after g';console.log(`${ label }: ${ value }`);return value;};constg= n => n +1;constf= n => n *2;consth=pipe( g, traceAfterG, f,trace('after f'),);h(20);