根據條件傳回不同 function

寫程式免不了要使用 if else 判斷,但 if else 是 Imperative 產物,這種寫法會使得 Pipeline 中斷而無法 Compose Function,所幸 Ramda 亦提供 ifElse() operator,使我們能不中斷繼續 Pipeline。

Version


WebStorm 2018.3.3
Quokka 1.0.134
Ramda 0.26.1

Array.prototype


1
2
3
4
5
6
7
8
9
const data = [1, 2, 3];

const findIndexDefault = (fn, defaultIndex, data) => {
const result = data.findIndex(fn);
if (result === -1) return defaultIndex;
return result;
};

console.log(findIndexDefault(x => x === 4, 0, data));

ECMAScript 在 Array.prototype 提供了 findIndex(),可傳入 function 當判斷條件,若找到傳回 index,若找不到傳回 -1

但實務上可能不想傳回傳 -1,而希望自行提供 default index,若找不到則傳回 default index。

若使用 if 判斷 -1,則 findIndex() 的 pipeline 就中斷了 ,又回到 Imperative 的寫法。

if000

ifElse()


1
2
3
4
5
6
7
8
9
10
import { always, equals, findIndex, identity, ifElse, pipe } from 'ramda';

const data = [1, 2, 3];

export const findIndexDefault = (fn, defaultIndex, data) => pipe(
findIndex,
ifElse(equals(-1), always(defaultIndex), identity),
)(fn, data);

console.log(findIndexDefault(equals(4), 0, data));

Ramda 亦提供 findIndex(),功能與 Array.prototypefindIndex() 完全相同,沒找到也是傳回 -1,唯 data 放在最後一個參數,因此可以 Point-free。

findIndex()
(a -> boolean) -> [a] -> number
根據條件傳回 array 的 index,若找不到則傳回 -1

(a -> boolean):搜尋的條件

[a]:data 為 array

number:在 array 內的 index,找不到則回傳 -1

由於我們提供了 defaultIndex 參數,因此勢必使用 if else 判斷是否為 -1,Ramda 亦提供了 ifElse()

ifElse()
(*... -> boolean) -> (*...-> *) -> (*...-> *) -> (*... -> *)
根據條件傳回不同 function

(*... -> boolean):任意參數的 function,只要最後傳回 boolean 即可
(*...-> *):任意參數的 function,回傳也不拘
(*...-> *):任意參數的 function,回傳也不拘
(*...-> *):若為 true 則回傳第二個參數 function,若為 false 則傳回第三個參數 function

因此 ifElse() 第一個參數傳入了 equals(-1)

第二個參數為 true 所回傳 function,應該為 defaultIndex,但 ifElse() 要求為 function,因此需透過 always() 再做一次封裝成 function。

always()
a -> (* -> a)
產生無論輸入任何值,都回傳固定值的 function

a:任意值

(* -> a):回傳該值的 function

第三個參數為 false 所回傳 function,也就是 defaultIndex() 所回傳的值,但 ifElse() 要求為 function,因此需透過 identity() 再做一次封裝成 function。

identity()
a -> a
產生回傳與原本輸入值相同的 function

a:任意值

a:回傳亦為任意值

if001

Conclusion


  • ifElse() operator 讓我們在 Pipeline 也可以使用 if else 判斷,卻不會中斷 Pipeline
  • 若回傳為固定值,可使用 always() operator 產生 function
  • 若回傳為相同值,可使用 identity()operator 產生 function

Reference


Ramda, findIndex()
Ramda, ifElse()
Ramda, always()
Ramda, identity()