成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

函數(shù)式編程之柯里化和組合詳解

Jonathan Shieber / 1423人閱讀

摘要:提到函數(shù)式編程,就不得不提柯里化和組合。說實話,在之前的項目開發(fā)中,對柯里化和組合的運用不是太多,因為不太清楚應(yīng)該在哪些情況下應(yīng)該使用它們。所以在這篇文章中,我們將詳細(xì)的介紹柯里化和組合的用法以及使用場景。

提到函數(shù)式編程,就不得不提柯里化和組合。說實話,在之前的項目開發(fā)中,對柯里化和組合的運用不是太多,因為不太清楚應(yīng)該在哪些情況下應(yīng)該使用它們。所以在這篇文章中,我們將詳細(xì)的介紹柯里化和組合的用法以及使用場景。

柯里化 Curry

首先說說什么是柯里化, 簡單來講就是部分應(yīng)用, 也就是說 只傳遞函數(shù)的一部分參數(shù)來調(diào)用它,讓它返回一個函數(shù)去處理剩下的參數(shù)。

參數(shù)復(fù)用

先來看個例子,創(chuàng)建一個 say 函數(shù),打印出帶有名字,前綴和問候語的一句話。

const say = (name, prefix, greeting) => `${greeting}, ${prefix} ${name}!`;

say("Tom", "Mr", "Hello"); // "Hello, Mr Tom"
say("James", "Mr", "Hello"); // "Hello, Mr James"

在上面的例子中,我們每一次調(diào)用 say 函數(shù)都必須傳入完整的三個參數(shù),才能保證正確的運行結(jié)果,否則,雖然程序還是會正常運行,可是未傳入的部分會變成 undefined。

利用柯里化,我們可以固定住其中的部分參數(shù),在調(diào)用的時候,這個參數(shù)就相當(dāng)于已經(jīng)被記住了,不需要再次傳遞,也就是我們這里說的參數(shù)復(fù)用。

const say = prefix => greeting => name => `${greeting}, ${prefix} ${name}!`;
const sayToMr = say("Mr");
const sayToMiss = say("Miss");
const greetMr = sayToMr("Hello");
const greetMiss = sayToMiss("Hi");

greetMr("Tom"); // "Hi, Miss Cindy!"
greetMiss("Cindy"); // "Hello, Mr Tom!"

這時候如果我們想輸入相同的問候語 Hello, 我們發(fā)現(xiàn),原來的結(jié)構(gòu)好像不太滿足了呃,于是我們開始調(diào)整參數(shù)的位置。

const say = greeting => prefix => name => `${greeting}, ${prefix} ${name}!`;
const greet = say("Hello");
const greetMeiNv = greet("美女");
const greetShuaiGe = greet("帥哥");

greetShuaiGe("Tom"); // "Hello, 帥哥 Tom!"
greetMeiNv("Cindy"); // "Hello, 美女 Cindy!"
Note: 在使用柯里化的時候,參數(shù)的順序很重要,可以考慮根據(jù)易變化的程度來排列參數(shù),把不容易變化的參數(shù)通過柯里化固定起來,將需要處理的參數(shù)放到最后一位。
延遲執(zhí)行

在上面的例子中,通過柯里化,我們居然多造出了 3 個函數(shù)!簡直就是函數(shù)工廠嘛!但是猛地一想,如果如果是 100 個參數(shù)呢,難道要寫一百次?有沒有一種方法可以簡單的幫我們實現(xiàn)柯里化?

我要開始放書上的代碼了。

function curry(fn) {
  var outerArgs = Array.prototype.slice.call(arguments, 1);
  
  return function() {
    var innerArgs = Array.prototype.slice.call(arguments),
      finalArgs = outerArgs.concat(innerArgs);
    return fn.apply(null, finalArgs);
  };
}

const say = (name, prefix, greeting) => `${greeting}, ${prefix} ${name}!`;

const curriedSay = curry(say);
curriedSay("Tom", "Mr", "Hello"); // "Hello, Mr Tom!"
curry(say,"Tom", "Mr")("Hello");  // "Hello, Mr Tom!"

簡單解釋一下上面的代碼,首先是得到除了第一個參數(shù) fn 之外的所有的外部傳參 outerArgs,這里的 arguments 是一個長得像數(shù)組的對象,所以我們要使用 Array.proptype.slice 將其轉(zhuǎn)變成真正的數(shù)組。 innerArgs 用來獲取調(diào)用這個匿名函數(shù)時的傳參。最后將外部傳參 outerArgs 和內(nèi)部傳參 innerArgs 合并,調(diào)用 fn。也就是說這時 fn 才被調(diào)用。

就好比刷信用卡和儲蓄卡,刷儲蓄卡就是把你的錢馬上轉(zhuǎn)到別人口袋,刷信用卡是銀行先幫你墊著,到下個月再把錢還給銀行。總之,最后都是花自己的錢。不過這樣有一個好處就是,就是可以讓你養(yǎng)成拆分函數(shù),并給函數(shù)良好命名的習(xí)慣,以及更好的處理和抽象代碼的邏輯。

使用 Ramda / Lodash 生成柯里化函數(shù)

當(dāng)然,你也可以可以使用 lodash 或者 ramda 這樣的庫來快速柯里化你的函數(shù),這樣可以省去很多重復(fù)造輪子的工作。

下面以使用 lodash 為例。

const say = (prefix, name, greeting) => `${greeting}, ${prefix} ${name}!`;
const curreiedSay = _.curry(say);

curreiedSay("Mr","Tom","Hello"); // "Hello, Mr Tom!"
curreiedSay("Mr")("Tom","Hello"); // "Hello, Mr Tom!"
curreiedSay("Mr")("Tom")("Hello"); // "Hello, Mr Tom!"
curreiedSay("Tom")(_,"Hello")("Mr"); // "Hello, Mr Tom!"
lodash 和 Ramda 都提供了一系列柯里化函數(shù)的包裝方法,感興趣的同學(xué)可以打開 lodash / ramda 官網(wǎng),在 console 里面試一下。
組合 Compose

組合,顧名思義,也就是把多個函數(shù)組合起來變成一個函數(shù)。

const compose = (fn1, fn2) => args => fn1(fn2(args));

const toUpperCase = value => value.toUpperCase();
const addSuffix = value => `${value} is good!`;

const format = compose(toUpperCase, addSuffix);
format("apple"); // "APPLE IS GOOD!"

上面的例子中,fn2 先執(zhí)行,然后將返回值作為 fn1 的參數(shù),所以 compose 里面的方法是從右向左執(zhí)行的。就像一條流水線一樣,a 流水線先把汽車組裝好,然后交給 b 流水線進(jìn)行噴漆,再交給 c 流水線打磨等等,最后得到一輛嶄新的汽車。

結(jié)合柯里化和組合 Curry + Compose

學(xué)習(xí)完柯里化和組合之后,讓我們將它們結(jié)合起來使用,一定能夠碰撞出更強(qiáng)的火花,產(chǎn)生更大的威力。

說寫就寫。

假設(shè)有一個數(shù)組,我們期望先對數(shù)組進(jìn)行去重,然后對數(shù)組進(jìn)行求和或求積。

const unique = arr => _.uniq(arr); // 數(shù)組去重
const sum = arr => _.reduce(arr, (total, n) => total + n); // 數(shù)組元素的累加之和

const multiply = arr => _.reduce(arr, (total, n) => total * n); // 數(shù)組元素的乘積

const getTotal = fn => arr => _.flowRight(fn, unique)(arr); // 從右至左, 先去重, 再執(zhí)行 fn

const arr1 = [1, 2, 3, 4, 4, 5, 5];
const arr2 = [1, 2, 2, 3, 4, 4, 5];

const getSumTotal = getTotal(sum); // 通過柯里化產(chǎn)生一個新的函數(shù)
const getMultiplyTotal = getTotal(multiply);   // 通過柯里化產(chǎn)生一個新的函數(shù)

getSumTotal(arr1); // 15
getMultiplyTotal(arr2); // 120

現(xiàn)在的前端社區(qū)中,函數(shù)式編程隨處可見,柯里化和組合也成為了我們必須掌握的技能。在項目開發(fā)中,可以不斷的去加強(qiáng)練習(xí)。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/91134.html

相關(guān)文章

  • SegmentFault 技術(shù)周刊 Vol.16 - 淺入淺出 JavaScript 函數(shù)編程

    摘要:函數(shù)式編程,一看這個詞,簡直就是學(xué)院派的典范。所以這期周刊,我們就重點引入的函數(shù)式編程,淺入淺出,一窺函數(shù)式編程的思想,可能讓你對編程語言的理解更加融會貫通一些。但從根本上來說,函數(shù)式編程就是關(guān)于如使用通用的可復(fù)用函數(shù)進(jìn)行組合編程。 showImg(https://segmentfault.com/img/bVGQuc); 函數(shù)式編程(Functional Programming),一...

    csRyan 評論0 收藏0
  • JavaScript函數(shù)編程,真香組合(一)

    摘要:組合的概念是非常直觀的,并不是函數(shù)式編程獨有的,在我們生活中或者前端開發(fā)中處處可見。其實我們函數(shù)式編程里面的組合也是類似,函數(shù)組合就是一種將已被分解的簡單任務(wù)組織成復(fù)雜的整體過程。在函數(shù)式編程的世界中,有這樣一種很流行的編程風(fēng)格。 JavaScript函數(shù)式編程,真香之認(rèn)識函數(shù)式編程(一) 該系列文章不是針對前端新手,需要有一定的編程經(jīng)驗,而且了解 JavaScript 里面作用域,閉...

    mengbo 評論0 收藏0
  • 函數(shù)編程的興衰與當(dāng)前崛起

    摘要:函數(shù)式編程逐漸被邊緣化,被拋棄到學(xué)術(shù)界和非主流的場外。組合式編程的重新崛起年左右,有個巨大的變化爆發(fā)了。人們開始逐漸在私下里談?wù)摵瘮?shù)式編程。箭頭函數(shù)對于函數(shù)式編程的爆發(fā)起到了推動劑的作用?,F(xiàn)在很少看到那種不用函數(shù)式編程的大型應(yīng)用了。 showImg(https://segmentfault.com/img/remote/1460000009036867?w=800&h=364); 本...

    binaryTree 評論0 收藏0
  • 全本 | iKcamp翻譯 | 《JavaScript 輕量級函數(shù)編程》|《你不知道的JS》姊妹篇

    摘要:本書主要探索函數(shù)式編程的核心思想。我們在中應(yīng)用的僅僅是一套基本的函數(shù)式編程概念的子集。我稱之為輕量級函數(shù)式編程。通常來說,關(guān)于函數(shù)式編程的書籍都熱衷于拓展閱讀者的知識面,并企圖覆蓋更多的知識點。,本書統(tǒng)稱為函數(shù)式編程者。 原文地址:Functional-Light-JS 原文作者:Kyle Simpson?。 禮ou-Dont-Know-JS》作者 譯者團(tuán)隊(排名不分先后)...

    paney129 評論0 收藏0
  • 翻譯連載 | JavaScript 輕量級函數(shù)編程-第3章:管理函數(shù)的輸入 |《你不知道的JS》姊

    摘要:但是,對函數(shù)式編程而言,這個行為的重要性是毋庸置疑的。關(guān)于該模式更正式的說法是偏函數(shù)嚴(yán)格來講是一個減少函數(shù)參數(shù)個數(shù)的過程這里的參數(shù)個數(shù)指的是希望傳入的形參的數(shù)量。 原文地址:Functional-Light-JS 原文作者:Kyle Simpson-《You-Dont-Know-JS》作者 關(guān)于譯者:這是一個流淌著滬江血液的純粹工程:認(rèn)真,是 HTML 最堅實的梁柱;分享,是...

    xiaowugui666 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<