2019-09-14
map()
的 Callback 常需要常需要從 Object 取得 Property,可使用 Ramda 的 prop()
使 Callback 能 Point-free。
Version
macOS Mojave 10.14.6
VS Code 1.38.1
Quokka 1.0.244
Ramda 0.26.1
Imperative
let data = [1, 2, 3];
let lut = {
1: 'FP in JavaScript',
2: 'RxJS in Action',
3: 'Speaking JavaScript',
};
let fn = arr => {
let result = [];
for(let x of arr)
result.push(lut[x]);
return result;
};
fn(data);
一個實務上常見的需求,由 API 所得到的資料只有 代碼
,而我們需要根據 代碼
轉成 對應資料
顯示。
至於 代碼
與 顯示文字
的對照表,會存在 lut
內。
Imperative 會使用 for
loop,若在 lut
比對到,則 push()
到新的 result
array,最後回傳 result
array。
Array.prototype.map()
let data = [1, 2, 3];
let lut = {
1: 'FP in JavaScript',
2: 'RxJS in Action',
3: 'Speaking JavaScript',
};
let fn = arr => arr.map(x => lut[x]);
fn(data);
Array.prototype
有自帶 map()
,所以我們也可以直接使用,再透過 lut[x]
加以對照轉換。
這種寫法已經比 Imperative 精簡很多,但仍有兩個問題:
- 由於內建的
map()
不是 curry function,因此fn()
仍然要提供arr
argument,無法如 point-Free 那樣精簡 x => lut[x]
這種 callback,是否有 point-free 寫法呢 ?
map()
import { map } from 'ramda';
let data = [1, 2, 3];
let lut = {
1: 'FP in JavaScript',
2: 'RxJS in Action',
3: 'Speaking JavaScript',
};
let fn = map(x => lut[x]);
fn(data);
Ramda 亦提供 map()
,與 Array.prototype.map()
不同在於他是個 curry function,最後一個參數為 data
,因此 fn()
可以使用 point-free 寫法,程式碼更精簡。
map()
(a -> b) -> a -> b
將 a 格式資料轉換成 b 格式資料,且筆數不變
(a -> b)
: map()
要轉換的 callback
[a]
:data 為 array
[b]
:回傳為新的 array
由於最後一個 argument 為 data
,使得 map()
可使用 point-free。
prop()
import { map, prop, __ } from 'ramda';
let data = [1, 2, 3];
let lut = {
1: 'FP in JavaScript',
2: 'RxJS in Action',
3: 'Speaking JavaScript',
};
let fn = map(
prop(__, lut)
);
fn(data);
不過之前的寫法,map()
的 callback 仍然不是 point-free,Ramda 特別提供了 prop()
,專門產生這類 callback。
Ramda 的 function 最後一個 argument 都是 data,因此可以很簡單的省略 data 做 point-free,但本文需求有些特別,map()
傳進來的資料並不是 prop()
最後一個 argument,而是第一個 argument。
對於這種特殊需求,Ramda 另外提供 __
function 做 placeholder,專門負責傳入 data。
prop()
s -> {s: a} -> a | undefined
傳入 key 與 object,傳回 value
s
:object 的 key
{s: a}
:data 為 object
a | undefined
:傳回 value,若找不到為 undefined
flip()
import { map, prop, flip } from 'ramda';
let data = [1, 2, 3];
let lut = {
1: 'FP in JavaScript',
2: 'RxJS in Action',
3: 'Speaking JavaScript',
};
let fn = map(
flip(prop)(lut)
);
fn(data);
若不想使用 __
,也可以使用 flip()
,將 prop()
的兩個 argument 順序調換,則可以使用 point-free。
flip()
((a, b, c, ...) -> z) -> (b -> a -> c -> ... -> z)
將 function 的前兩個 argument 順序調換,以配合 point-free
Conclusion
prop()
會傳回 Ramda 所需要的 callback,只要傳入 object 的 property 名稱即可- FP 的 data 都會放在最後一個 argument,因此可輕鬆做 point-free,但若剛好不是最後一個argument,可使用
__
做 placeholder - 也可以使用
flip()
將 argument 順序調換
Reference
-
使用 pluck() 將 Array 中 Object 的指定 Property 取出
原文:大专栏 使用 prop() 取得 Object 的 Property
原文地址:https://www.cnblogs.com/chinatrump/p/11584742.html