使用 call() 動態產生 Converging Function

Ramda 的 call() 乍看很不起眼,但若搭配 converge() 之後,就能動態產生 Converging Function。

Version

macOS Mojave 10.14.5

VS Code 1.32.3

Quokka 1.0.195

Ramda 0.26.1

call()

import { call,add} from'ramda';call(add, 1, 2); // ?

最簡單的 call() ,第一個 argument 為 function,第二個 argument 之後為該 function 的 argument list,相當於執行 add(1, 2) 。

call()

(*… → a),*… → a 

執行第一個 argument 的 function,並將之後 argument 當作該 function 的 argument list

(*… → a) :任意 function

*… :任意 argument list

a :回傳 function 執行的結果

使用 call() 動態產生 Converging Function_第1张图片

Function

letproduct = {discount:5000,price:30000};// calPrice :: (Number, Number) -> NumberletcalPrice =(discount, price) =>price - discount -1000;// finalPrice :: Number -> NumberletfinalPrice =product=>calPrice(product.discount, product.price);finalPrice(product);// ?

calPrice() 傳入 discount 與 price argument,會計算出折扣後價錢。

fn() 則傳入 product object,再呼叫 calPrice() 。

使用 call() 動態產生 Converging Function_第2张图片

Point-free

import{ converge, prop }from'ramda';letproduct = {discount:5000,price:30000};// calPrice :: (Number, Number) -> NumberletcalPrice =(discount, price) =>price - discount -1000;// finalPrice :: Number -> NumberletfinalPrice = converge(  calPrice, [    prop('discount'),    prop('price')  ]);finalPrice(product);// ?

首先將 finalPrice() point-free。

11 行

// finalPrice :: Number -> NumberletfinalPrice = converge(  calPrice, [    prop('discount'),    prop('price')  ]);

finalPrice() 的 argument 為 product object,包含 discount 與 price property,分別傳入 折扣 與 價錢 。

最後要執行的是 calPrice() ,分別有 discount 與 price 兩個 argument。

由於傳入 finalPrice() 的是 object,因此勢必要先使用 prop() 拆解後才能傳給 calPrice()執行。

這正是使用 finalPrice() 時機,將 calPrice() 當作 converging function,將 prop() 當作 branching function。

就功能而言沒問題,唯 calPrice() 並非 point-free,是否有繼續優化空間呢 ?

使用 call() 動態產生 Converging Function_第3张图片

import { converge, prop, call,add, pipe, subtract, flip, compose }from'ramda';letproduct = {  discount:5000,  price:30000};// calPrice :: (Number, Number) -> NumberletcalPrice = pipe(add(1000),  flip(subtract));// getDiscount :: Object -> NumberletgetDiscount = compose(calPrice, prop('discount'));// getPrice :: Object -> NumberletgetPrice = prop('price');// finalPrice :: Number -> NumberletfinalPrice = converge(  call, [    getDiscount,    getPrice  ]);finalPrice(product);// ?

由於 calPrice() 有兩個 argument: discount 與 price ,基於 currying 特性,可將 calPrice() 視為由 discount 產生的 function,其 argument 只剩下 price 。

第 8 行

//calPrice ::(Number, Number)->Numberlet calPrice = pipe(  add(1000),  flip(subtract));

calPrice() 最直覺會想用 pipe() ,多減 1000 元就相當於 discount 多加 1000 元,所以先套用 add(1000) 將 discount 加 1000 ,再傳到下一個 subtract() 。

但 subtract() 第一個 argument 為 被減數 ,而 add(1000) 為 減數 ,因此必須使用 flip()將 subtract() 的 signature 反轉後才能使用。

我們發現 calPrice() 已經 point-free 了。

21 行

// finalPrice :: Number -> NumberletfinalPrice = converge(  call, [    getDiscount,    getPrice  ]);

由於 calPrice() 由 discount 產生,因此 converge() 的 converging function 就不能再是 calPrice() ,而要改用 call() ,如此才會執行第一個 branching function。

第一個 branching function getDiscount() 以取得 discount 為目標。

第二個 branching function getPrice() 以取得 price 為目標,再傳入第一個 branching function 執行,這是因為 call() 的緣故。

14 行

// getDiscount :: Object -> NumberletgetDiscount = compose(calPrice, prop('discount'));

從 object 取得 discount property,然後透過 calPrice() 計算。

17 行

// getPrice :: Object -> NumberletgetPrice = prop('price');

從 object 取得 price property。

使用 call() 動態產生 Converging Function_第4张图片

如果有想学习编程的初学者,可来我们的前端直播授课群的哦:571671034里面免费送整套系统的前端教程! 

你可能感兴趣的:(使用 call() 動態產生 Converging Function)