如何自行實作 compose() 與 pipe() ?
栏目: JavaScript · 发布时间: 6年前
内容简介:VS Code 1.35.1Quokka 1.0.227
compose() 與 pipe() 是 FP 最重要兩個 Function,其中 Function Composition 就是由這兩個 Function 展開,實務上都是直接使用 Ramda 或 Crocks 所提供的 compose() 與 pipe() ,能自己使用 ECMAScript 實現嗎 ?
Version
VS Code 1.35.1
Quokka 1.0.227
Ramda 0.26.1
Ramda
import { compose, filter, map } from 'ramda';
let data = [
{ title: 'FP in JavaScript', price: 100 },
{ title: 'RxJS in Action', price: 200 },
{ title: 'Speaking JavaScript', price: 300 }
];
// fn :: Number -> [a] -> [b]
let fn = price => compose(
map(x => x.title),
filter(x => x.price === price),
);
fn(300)(data); // ?
在Ramd 初體驗 一文中,曾經使用 Ramda 最具代表性的 compose() 、 filter() 與 map() 實現 function composition。
其中 compose() 為 Ramda 所提供。
compose()
import { filter, map } from 'ramda';
let data = [
{ title: 'FP in JavaScript', price: 100 },
{ title: 'RxJS in Action', price: 200 },
{ title: 'Speaking JavaScript', price: 300 }
];
// compose :: ((y → z), (x → y), …, (o → p), ((a, b, …, n) → o)) → ((a, b, …, n) → z)
let compose = (...fns) => fns.reduce((f, g) => (...args) => f(g(...args)));
// fn :: Number -> [a] -> [b]
let fn = price => compose(
map(x => x.title),
filter(x => x.price === price),
);
fn(300)(data); // ?
第 1 行
import { filter, map } from 'ramda';
沒使用 Ramda 所提供的 compose() 。
第 9 行
// compose :: ((y → z), (x → y), …, (o → p), ((a, b, …, n) → o)) → ((a, b, …, n) → z) let compose = (...fns) => fns.reduce((f, g) => (...args) => f(g(...args)));
自行使用 ECMAScript 內建的 reduce() 實現 compose() 。
(...fns)
使用 ES6 的 rest parameter,表示 compose() 的 argument 個數無限,且 fns 為 array,因此可大膽使用 Array.prototype 下的 method。
(f, g) => (...args) => f(g(...args))
g 為目前 function, f 為組合後 function,因為結果仍是 function,所以為 (...args) => f(g(...args)) 。
reduce() 為 array 的 由左至右 ,因此最後 element 為 g ,相當於 compose() 的 由右至左 運算。
pipe()
import { filter, map } from 'ramda';
let data = [
{ title: 'FP in JavaScript', price: 100 },
{ title: 'RxJS in Action', price: 200 },
{ title: 'Speaking JavaScript', price: 300 }
];
// pipe :: (((a, b, …, n) → o), (o → p), …, (x → y), (y → z)) → ((a, b, …, n) → z)
let pipe = (...fns) => fns.reduceRight((f, g) => (...args) => f(g(...args)));
let fn = price => pipe(
filter(x => x.price === price),
map(x => x.title),
);
fn(300)(data); // ?
第 1 行
import { filter, map } from 'ramda';
沒使用 Ramda 所提供的 pipe() 。
第 9 行
// (((a, b, …, n) → o), (o → p), …, (x → y), (y → z)) → ((a, b, …, n) → z) let pipe = (...fns) => fns.reduceRight((f, g) => (...args) => f(g(...args)));
pipe() 為 由左至右 運算,也就是 array 的 由右至左 ,因此使用 reduceRight() 。
Conclusion
-
compose()與pipe()一直被認為是黑魔法,事實上只是將 function 加以reduce()而已,能自己寫過一次,就不會覺得那麼遙不可及了
以上所述就是小编给大家介绍的《如何自行實作 compose() 與 pipe() ?》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。