内容简介: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。
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 精簡很多,但仍有兩個問題:
- 由於內建的
map()
不是 Curried Function,因此getBooks()
仍然要提供data
參數,無法如 Point-Free Style 那樣精簡 -
map()
的 Arrow Function 為一次性 function,無法重複使用
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.prototype
的 map()
不同在於:他是個 Curried Function,最後一個參數為 data
,因此 getBooks()
可以使用 Point-Free Style 方式建立,如此將省下一個參數,程式碼更精簡。
map()
(a -> b) -> a -> b
將 a 格式資料轉換成 b 格式資料,且筆數不變
第一個參數 (a -> b)
為 function,也就是 map()
要轉換的 function。
第二個參數 a
為 data
,也由於最後一個參數為 data
,使得 map()
可使用 Point-Free Style。
回傳 b
,也就是新的 data
。
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()
。
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,重複使用程度大大提高。
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
Conclusion
curry() curry()
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
JSON 在线解析
在线 JSON 格式化工具
HEX CMYK 转换工具
HEX CMYK 互转工具