如何自行實作 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() 與 pipe() ?

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()由右至左 運算。

如何自行實作 compose() 與 pipe() ?

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()

如何自行實作 compose() 與 pipe() ?

Conclusion

  • compose()pipe() 一直被認為是黑魔法,事實上只是將 function 加以 reduce() 而已,能自己寫過一次,就不會覺得那麼遙不可及了

以上所述就是小编给大家介绍的《如何自行實作 compose() 與 pipe() ?》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

知识的边界

知识的边界

[美] 戴维·温伯格 / 胡泳、高美 / 山西人民出版社 / 2014-12-1 / 42.00元

大数据时代反思知识 因为事实不再是事实,专家随处可见 所有确定性都被连根拔起,话题再无边界,没有人对任何事情能达成一致。 在互联网的引领下,知识现在已经具有了社交性,流动且开放。温伯格向我们展示了这些特点如何可以为我们所用。 ——马克•贝尼奥夫(云计算之父,著有《云攻略》) 这本富有洞见的著作,奠定了温伯格作为数字时代最重要的思想家之一的地位。如果你想要理解信息洪流涌......一起来看看 《知识的边界》 这本书的介绍吧!

随机密码生成器
随机密码生成器

多种字符组合密码

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具