天天看點

JavaScript函數程式設計-Ramdajs

JavaScript函數程式設計-Ramdajs

在javascript語言世界,函數是第一等公民。javascript函數是繼承自function的對象,函數能作另一個函數的參數或者傳回值使用,這便形成了我們常說的高階函數(或稱函數對象)。這就構成函數程式設計的第一要素。在javascript世界中有很多的函數式程式設計庫能輔助我們的javascript函數式體驗,在它們之中最為成功的要數underscore或lodash。

如下lodash執行個體代碼:

函數式思想展現的是一種純粹的數學思維。函數并不代表任何物質(對象,相對于面向對象思想而言),而它僅僅代表一種針對資料的轉換行為。一個函數可以是原子的算法子(函數),也可以是多個原子算法子組成的組合算法子。它們是對行為的最高抽象,具有非凡的抽象能力和表現力。

雖然underscore或lodash也提供了.compose(或.flowright)函數來實作函數組合的能力,但ramdajs具有更強的組合力。

在計算機科學中,柯裡化(currying)是把接受多個參數的函數變換成接受一個單一參數(最初函數的第一個參數)的函數,并且傳回接受餘下的參數且傳回結果的新函數的技術。這個技術由 christopher strachey 以邏輯學家 haskell curry 命名的,盡管它是 moses schnfinkel 和 gottlob frege 發明的。

在理論計算機科學中,柯裡化提供了在簡單的理論模型中比如隻接受一個單一參數的lambda 演算中研究帶有多個參數的函數的方式。

ramdajs利用這一技術,預設所有api函數都支援自動柯裡化。這為它提供了可以将另一個函數組合的先決條件。如常用的map操作需要接受兩個參數,在ramdajs中可以如下兩種方式實作:

如果我們傳入2個完備的參數,則r.map函數将會直接執行。否則,它将傳回另一個函數,等待參數完備時才執行。

在underscore和lodash這類庫中,都要求首先傳入資料,然後才是轉換函數。而在ramdajs卻是颠覆性的改變。在它的規約中資料參數是最後一個參數,而轉換函數和配置參數則優于資料參數,排在前面。

将轉換函數放置在前面,再加上函數的自動柯裡化,就可以在不觸及資料的情況下,将一個函數算法子包裝進另一個算法子中,實作兩個獨立轉換功能的組合。

假設,我們擁有如下兩個基礎算法子:

r.multiply(a, b):實作 a *b; 2:r.map(func, data):實作集合 a –> b的map。

因為可以自動柯裡化,是以有

是以上面對數組map的例子則可以轉為如下形式:

r.map(r.multiply(2))的傳回值也是一個函數,它是一個組合轉換函數。它組合了map和multiply行為。它利用r.map組合封裝了r.multiply(2)傳回的柯裡化函數,它等待map函數傳入對應的被乘數。

有了上面的兩個條件,再加上ramdajs為我們提供的r.compose方法,我們就能很容易的實作更多算法子的組合。r.compose是從右向左執行的資料流向。

用ramdajs的組合來實作開篇lodash一樣的使用者名拼接的例子,則我們可以分為2個算法子的組合:

r.pluck(prop):選擇對象固定屬性;

r.join(data):對數組的字元串拼接。

則代碼如下所示:

這裡的函數式組合可表示為下圖:

JavaScript函數程式設計-Ramdajs

如果我們希望join使用者的年齡,則如下:

假設我們希望輸出的不是使用者年齡,而是使用者生日,則我們可以輕易組合上一個減法的算法子:

r.subtract(a, b):實作 a – b 數學算法。

則代碼如下:

再如,我們希望擷取最年輕的使用者:

lodash實作:

ramdajs則,可以組合擷取第一個元素的r.head算法子和排序算法子r.sortby:

比如我們希望擷取年長的使用者,則隻需再組合一個反序排列的算法子r.reverse:

繼續閱讀