如何自行實作 compose() 與 pipe() ?
栏目: JavaScript · 发布时间: 5年前
内容简介: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() ?》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。