成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

函數(shù)式編程 - 組合compose

zhangrxiang / 1829人閱讀

摘要:函數(shù)式編程中有一個比較重要的概念就是函數(shù)組合組合多個函數(shù),同時返回一個新的函數(shù)。深入理解認識函數(shù)式編程里面跟類似的方法,就是。主要作用也是組合多個函數(shù),稱之為流,肯定得按照正常方法,從左往右調(diào)用函數(shù),與調(diào)用方法相反。

函數(shù)式編程中有一個比較重要的概念就是函數(shù)組合(compose),組合多個函數(shù),同時返回一個新的函數(shù)。調(diào)用時,組合函數(shù)按順序從右向左執(zhí)行。右邊函數(shù)調(diào)用后,返回的結果,作為左邊函數(shù)的參數(shù)傳入,嚴格保證了執(zhí)行順序,這也是compose 主要特點。

入門簡介 組合兩個函數(shù)

compose 非常簡單,通過下面示例代碼,就非常清楚

function compose (f, g) {
    return function(x) {
        return f(g(x));
    }
}

var arr = [1, 2, 3],
    reverse = function(x){ return x.reverse()},
    getFirst = function(x) {return x[0]},
    compseFunc = compose(getFirst, reverse);
    
compseFunc(arr);   // 3

參數(shù)在函數(shù)間就好像通過‘管道’傳輸一樣,最右邊的函數(shù)接收外界參數(shù),返回結果傳給左邊的函數(shù),最后輸出結果。

組合任意個函數(shù)

上面組合了兩個函數(shù)的compose,也讓我們了解了組合的特點,接著我們看看如何組合更多的函數(shù),因為在實際應用中,不會像入門介紹的代碼那么簡單。

主要注意幾個關鍵點:

利用arguments的長度得到所有組合函數(shù)的個數(shù)

reduce 遍歷執(zhí)行所有函數(shù)。

    var compose = function() {
      var args = Array.prototype.slice.call(arguments);
      
      return function(x) {
       if (args.length >= 2) {
       
          return args.reverse().reduce((p, c) => {
            return p = c(p)
         }, x)
         
       } else {
           return args[1] && args[1](x);
       }
      }
    }
   
    // 利用上面示例 測試一下。
    var arr = [1, 2, 3],
    reverse = function(x){ return x.reverse()},
    getFirst = function(x) {return x[0]},
    trace = function(x) {  console.log("執(zhí)行結果:", x); return x}
    
    
    compseFunc = compose(trace, getFirst, trace, reverse);
    
compseFunc(arr);   
 // 執(zhí)行結果: (3)?[3, 2, 1]
 // 執(zhí)行結果: 3
 // 3

如此實現(xiàn),基本沒什么問題,變量arr 在管道中傳入后,經(jīng)過各種操作,最后返回了結果。

深入理解 認識pipe

函數(shù)式編程(FP)里面跟compose類似的方法,就是pipe。
pipe,主要作用也是組合多個函數(shù),稱之為"流", 肯定得按照正常方法,從左往右調(diào)用函數(shù),與compose 調(diào)用方法相反。

ES6 實現(xiàn)Compose function

先看下compose 最基礎的兩參數(shù)版本,

const compose = (f1, f2) => value => f1(f2(value));

利用箭頭函數(shù),非常直接的表明兩個函數(shù)嵌套執(zhí)行的關系,

接著看多層嵌套。

    (f1, f2, f3...) => value => f1(f2(f3));

抽象出來表示:

     () => () => result;

先提出這些基礎的組合方式,對我們后面理解高級es6方法實現(xiàn)compose有很大幫助。

實現(xiàn)pipe

前面提到pipe 是反向的compose,pipe正向調(diào)用也導致它實現(xiàn)起來更容易。

pipe = (...fns) => x => fns.reduce((v, f) => f(v), x)
    

一行代碼就實現(xiàn)了pipe, 套用上面抽象出來的表達式,reduce剛好正向遍歷所有函數(shù), 參數(shù)x作為傳遞給函數(shù)的初始值, 后面每次f(v)執(zhí)行的結果,作為下一次f(v)調(diào)用的參數(shù)v,完成了函數(shù)組合調(diào)用。

或者,可以把函數(shù)組合中,第一個函數(shù)獲取參數(shù)后,得到的結果,最為reduce遍歷的初始值。

pipe = (fn,...fns) => (x) => fns.reduce( (v, f) => f(v), fn(x));

利用es6提供的rest 參數(shù) ,用于獲取函數(shù)的多余參數(shù).提取出第一個函數(shù)fn,多余函數(shù)參數(shù)放到fns中,fns可以看成是數(shù)組,也不用像arguments那種事先通過Array.prototype.slice.call轉(zhuǎn)為數(shù)組,arguments對性能損耗也可以避免。 fn(x) 第一個函數(shù)執(zhí)行結果作為reduce 初始值。

實現(xiàn)compose

pipe 部分,利用reduce實現(xiàn),反過來看,compose就可以利用reduceRight

compose = (...fns) => x => fns.reduceRight((v, f) => f(v), x);

利用遞歸

compose = (fn, ...fns) => fns.length === 0 ? fn: (...args) => fn(compose(...fns)(...args))

遞歸代碼,首先看出口條件, fns.length === 0, 最后一定執(zhí)行最左邊的函數(shù),然后把剩下的函數(shù)再經(jīng)過compose調(diào)用,

利用reduce實現(xiàn)。
具體實現(xiàn)代碼點擊這里,一行實現(xiàn),而且還是用正向的 reduce。

const compose = (...fns) => fns.reduce((f, g) => (...args) => f(g(...args)))

作者其實用例子做了解釋,可以看下reduce 迭代的方向是從左往右的,而compose 要求執(zhí)行的方向是從從右往左。對數(shù)組中每一項執(zhí)行函數(shù),正常情況下都應該放回執(zhí)行結果,比如(v, f) => f(v),返回f(v)執(zhí)行結果,這里是(f, g) => (...args) => f(g(...args))返回一個函數(shù)(...args) => f(g(...args)),這樣就可以保證后面的函數(shù)g在被作為參數(shù)傳入時比前面的函數(shù)f先執(zhí)行。

簡單利用前面的組合兩個函數(shù)的例子分析一下。

...
composeFunc = compose(getFirst, trace, reverse);
composeFunc(arr);
  

主要看reduce 函數(shù)里面的執(zhí)行過程:

入口 composeFunc(arr), 第一次迭代,reduce函數(shù)執(zhí)行 (getFirst, trace) => (...args)=>getFirst(trace(...args)),函數(shù)(...args)=>getFirst(trace(...args))作為下一次迭代中累計器f的值。

第二次迭代,reduce函數(shù)中

 f == (...args)=>getFirst(trace(...args))
 g == reverse。
 // 替換一下 (f, g) => (...args) => f(g(...args))
((...args)=>getFirst(trace(...args)), reverse) => (...args) => ((...args)=>getFirst(trace(...args)))(reverse(...args))

迭代結束,最后得到的comoseFunc就是

   // 對照第二次的執(zhí)行結果, (...args) => f(g(...args))

  (...args) => ((...args)=>getFirst(trace(...args)))(reverse(...args))

調(diào)用函數(shù)composeFunc(arr)。

(arr) => ((...args)=>getFirst(trace(...args)))(reverse(arr))

===》reverse(arr) 執(zhí)行結果[3, 2, 1] 作為參數(shù)

 ((...args)=>getFirst(trace(...args)))([3,2,1])

==》入?yún)⒄{(diào)用函數(shù)

   getFirst(trace[3,2,1])

===》 

   getFirst([3, 2, 1])

===》

   結果為 3

非常巧妙的把后一個函數(shù)的執(zhí)行結果作為包裹著前面函數(shù)的空函數(shù)的參數(shù),傳入執(zhí)行。其中大量用到下面的結構

((arg)=> f(arg))(arg) 
// 轉(zhuǎn)換一下。
  (function(x) {
     return f(x)
  })(x)

最后

無論是compose, 還是后面提到的pipe,概念非常簡單,都可以使用非常巧妙的方式實現(xiàn)(大部分使用reduce),而且在編程中很大程度上簡化代碼。最后列出優(yōu)秀框架中使用compose的示例:

redux/compose

koa-Compose

underscorejs/compose

參考鏈接

Creating an ES6ish Compose in Javascript

compose.js

Optimization-killers

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

轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/102266.html

相關文章

  • 函數(shù)編程組合

    摘要:在函數(shù)式編程的組合中,我們是從右到左執(zhí)行的,上述的例子中我們借助函數(shù)實現(xiàn)組合,當然,我們也可以用自己的方式實現(xiàn)。小結函數(shù)式編程隨著多核的發(fā)展,開始再次出現(xiàn)在我們的視野中,有時候也會擔心過于吹捧函數(shù)式,反而落入俗套。 程序的本質(zhì)是什么?數(shù)據(jù)結構+算法?。。∥蚁脒@也是很多程序員給出的答案,我自己也認可這一觀點,當我們了解了某一門編程語之后,接下來我們面對的往往是數(shù)據(jù)結構和算法的學習。而現(xiàn)在...

    Jinkey 評論0 收藏0
  • JavaScript函數(shù)編程函數(shù)組合函數(shù)compose和pipe的實現(xiàn)

    摘要:函數(shù)組合是函數(shù)式編程中非常重要的思想,它的實現(xiàn)的思路也沒有特別復雜。前者從左向右組合函數(shù),后者方向相反。下面就是一個最簡單的可以組合兩個函數(shù)的在實際應用中,只能組合兩個函數(shù)的組合函數(shù)顯然不能滿足要求,我們需要可以組合任意個函數(shù)的組合函數(shù)。 函數(shù)組合是函數(shù)式編程中非常重要的思想,它的實現(xiàn)的思路也沒有特別復雜。有兩種函數(shù)組合的方式,一種是pipe,另一種是compose。前者從左向右組合函...

    Cristalven 評論0 收藏0
  • JS每日一題:函數(shù)編程中代碼組合(compose)如何理解?

    摘要:期函數(shù)式編程中代碼組合如何理解定義顧名思義,在函數(shù)式編程中,就是將幾個有特點的函數(shù)拼湊在一起,讓它們結合,產(chǎn)生一個嶄新的函數(shù)代碼理解一個將小寫轉(zhuǎn)大寫的函數(shù)一個在字符后加的函數(shù)將兩個函數(shù)組合起來這里假設我們實現(xiàn)了每日一題每日一題顯示結果里上面 20190315期 函數(shù)式編程中代碼組合(compose)如何理解? 定義: 顧名思義,在函數(shù)式編程中,Compose就是將幾個有特點的函數(shù)拼湊在...

    Kaede 評論0 收藏0
  • 翻譯連載 | JavaScript輕量級函數(shù)編程-第4章:組合函數(shù) |《你不知道的JS》姊妹篇

    摘要:把數(shù)據(jù)的流向想象成糖果工廠的一條傳送帶,每一次操作其實都是冷卻切割包裝糖果中的一步。在該章節(jié)中,我們將會用糖果工廠的類比來解釋什么是組合。糖果工廠靠這套流程運營的很成功,但是和所有的商業(yè)公司一樣,管理者們需要不停的尋找增長點。 原文地址:Functional-Light-JS 原文作者:Kyle Simpson-《You-Dont-Know-JS》作者 關于譯者:這是一個流淌...

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

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

    mengbo 評論0 收藏0

發(fā)表評論

0條評論

閱讀需要支付1元查看
<