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

栏目: JavaScript · 发布时间: 7年前

内容简介: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-11 / 49.00元

几年前,“数学之美”系列文章原刊载于谷歌黑板报,获得上百万次点击,得到读者高度评价。读者说,读了“数学之美”,才发现大学时学的数学知识,比如马尔可夫链、矩阵计算,甚至余弦函数原来都如此亲切,并且栩栩如生,才发现自然语言和信息处理这么有趣。 在纸本书的创作中,作者吴军博士几乎把所有文章都重写了一遍,为的是把高深的数学原理讲得更加通俗易懂,让非专业读者也能领略数学的魅力。读者通过具体的例子学到的......一起来看看 《数学之美 (第二版)》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具