如何自行實作 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() 與 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() ?》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

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

Java技术手册(第6版)

Java技术手册(第6版)

Benjamin J Evans、David Flanagan / 安道 / 人民邮电出版社 / 2015-12-1 / 79.00

《Java技术手册 第6版》为《Java 技术手册》的升级版,涵盖全新的Java 7 和Java 8。第1部分介绍Java 编程语言和Java 平台,主要内容有Java 环境、Java 基本句法、Java 面向对象编程、Java 类型系统、Java的面向对象设计、Java 实现内存管理和并发编程的方式。第2部分通过大量示例来阐述如何在Java 环境中完成实际的编程任务,主要内容有编程和文档约定,使......一起来看看 《Java技术手册(第6版)》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具