Ramda 之 curry()

栏目: 编程语言 · 发布时间: 6年前

内容简介:Ramda 之Ramda 0.26.1一個實務上常見的需求,由 API 所得到的資料只有

Ramda 之 curry() 也是非常實用的 Operator,他能將普通 function 轉成 Curried Function,這在 FP 語言算是標準配備,但一直到目前為止,ECMAScript 都還沒有正式支援,而 Curried Function 對於寫出 Point-Free Style 有很大的貢獻。

Version

Ramda 0.26.1

Imperative

const data = [1, 2, 3];

const bookLut = {
  1: 'Functional Programming in JavaScript',
  2: 'RxJS in Action',
  3: 'Speaking JavaScript',
};

const getBooks = data => {
  let result = [];
  for(let item of data) {
    result.push(bookLut[item]);
  }
  return result;
};

const result = getBooks(data);
console.log(result);

一個實務上常見的需求,由 API 所得到的資料只有 代碼 ,而我們需要根據 代碼 轉成 對應資料 顯示。

至於 代碼顯示文字 的對照表,會存在 object 內。

Imperative 會使用 for loop,若在 object 比對到,則 push() 到新的 result array,最後回傳 result array。

Ramda 之 curry()

Array.prototype

const data = [1, 2, 3];

const bookLut = {
  1: 'Functional Programming in JavaScript',
  2: 'RxJS in Action',
  3: 'Speaking JavaScript',
};

const getBooks = data => data.map(x => bookLut[x]);

const result = getBooks(data);
console.log(result);

Array.prototype 有自帶 map() ,所以我們也可以直接使用,再透過 bookLut[x] 加以對照轉換。

這種寫法已經比 Imperative 精簡很多,但仍有兩個問題:

  1. 由於內建的 map() 不是 Curried Function,因此 getBooks() 仍然要提供 data 參數,無法如 Point-Free Style 那樣精簡
  2. map() 的 Arrow Function 為一次性 function,無法重複使用

Ramda 之 curry()

Ramda

import { map } from 'ramda';

const data = [1, 2, 3];

const bookLut = {
  1: 'Functional Programming in JavaScript',
  2: 'RxJS in Action',
  3: 'Speaking JavaScript',
};

const getBooks = map(x => bookLut[x]);

const result = getBooks(data);
console.log(result);

Ramda 亦提供 map() operator,與 Array.prototypemap() 不同在於:他是個 Curried Function,最後一個參數為 data ,因此 getBooks() 可以使用 Point-Free Style 方式建立,如此將省下一個參數,程式碼更精簡。

map()

(a -> b) -> a -> b

將 a 格式資料轉換成 b 格式資料,且筆數不變

第一個參數 (a -> b) 為 function,也就是 map() 要轉換的 function。

第二個參數 adata ,也由於最後一個參數為 data ,使得 map() 可使用 Point-Free Style。

回傳 b ,也就是新的 data

Ramda 之 curry()

import { map } from 'ramda';

const data = [1, 2, 3];

const bookLut = {
  1: 'Functional Programming in JavaScript',
  2: 'RxJS in Action',
  3: 'Speaking JavaScript',
};

const mapper = x => bookLut[x];
const getBooks = map(mapper);

const result = getBooks(data);
console.log(result);

不過之前寫法, map() 之後仍然是傳 Arrow Function,因此 重複使用 程度依然是 0

我們試著將 Arrow Function 抽成 mapper()

Ramda 之 curry()

import { map } from 'ramda';

const data = [1, 2, 3];

const bookLut = {
  1: 'Functional Programming in JavaScript',
  2: 'RxJS in Action',
  3: 'Speaking JavaScript',
};

const mapper = lut => x => lut[x];
const getBooks = map(mapper(bookLut));

const result = getBooks(data);
console.log(result);

雖然抽出了 mapper() ,但重複使用程度依然不高,因為直接耦合了 bookLut object。

比較好的方式是將 bookLut 也抽成參數,這樣 mapper() 可以用在其他 LUT object,重複使用程度大大提高。

Ramda 之 curry()

import { map, curry } from 'ramda';

const data = [1, 2, 3];

const bookLut = {
  1: 'Functional Programming in JavaScript',
  2: 'RxJS in Action',
  3: 'Speaking JavaScript',
};

const mapper = curry((lut, id) => lut[id]);
const getBooks = map(mapper(bookLut));

const result = getBooks(data);
console.log(result);

mapper() 雖然能重複使用,也能使用 Point-Free Style,但有個致命傷: Curried Form ,也就是要使用 mapper() 時,一定要 mapper(bookLut)(1) 這種形式。

這種寫法配合 map() 時不是問題,但若要讓 mapper() 單獨使用就很不方便,也不符合一般使用 ECMAScript function 的習慣。

比較好的方式是 mapper() 提供兩種方式:可以 mapper(bookLut, 1) 使用,亦可 mapper(bookLut)(1) 使用,如此 mapper() 實用程度就大大提高,既可以當成一般 function 使用,也可以搭配 Ramda 的 operator 做 Point-Free Style。

這時就要使用 Ramda 的 curry() operator,能將一般 function 轉成 Curried Form,亦能維持一般 function 的 signature。

curry()

(* -> a) -> (* -> a)

將普通 function 轉成 Curried Function

Ramda 之 curry()

Conclusion

curry()
curry()

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

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

关乎天下

关乎天下

关明生 / 学林出版社 / 2005-8 / 8.00元

《关乎天下:中小企业赢取江山的秘诀》收录了作者多年在大企业(如阿里巴巴网站)从事管理基层得到的经验,可为众多中小企业提供招贤纳士和销售管理方面的新思路。一起来看看 《关乎天下》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具