摘要:在函數(shù)式編程的組合中,我們是從右到左執(zhí)行的,上述的例子中我們借助函數(shù)實現(xiàn)組合,當然,我們也可以用自己的方式實現(xiàn)。小結(jié)函數(shù)式編程隨著多核的發(fā)展,開始再次出現(xiàn)在我們的視野中,有時候也會擔心過于吹捧函數(shù)式,反而落入俗套。
程序的本質(zhì)是什么?數(shù)據(jù)結(jié)構(gòu)+算法!??!我想這也是很多程序員給出的答案,我自己也認可這一觀點,當我們了解了某一門編程語之后,接下來我們面對的往往是數(shù)據(jù)結(jié)構(gòu)和算法的學習。而現(xiàn)在,我對于程序的本質(zhì)有了不一樣的答案:分化和組合。我的老師曾經(jīng)告訴我,工程師或者程序員有一個很重要的能力(我猜這也是最重要的能力),那就是發(fā)現(xiàn)和解決問題。而我目前只能接觸到解決問題的層次,這也是我也一直在探尋的目標 —— 分化和組合。
分化與組合在現(xiàn)實的程序開發(fā)中,我們碰到的問題一般是一個很大的命題,難以抽象,這時候往往通過分化子問題的方式對程序進行分而治之。在算法里,這種方式叫做分治。
將程序分化成可以抽象的子程序之后,再將他們組合成一個具有完備功能的程序。組合是程序或代碼可復用的前提,函數(shù)式編程中組合的使用也會給我們帶來意向不到的驚喜
Haskell 的組合Haskell是純函數(shù)式編程語言,他的強大不用我多說,這里展示一下他的組合能力。
compose :: (b -> c) -> (a -> b) -> a -> c compose f g = f . g
在函數(shù)式編程的組合中,我們是從右到左執(zhí)行的,上述的例子中我們借助 (.) 函數(shù)實現(xiàn)組合,當然,我們也可以用自己的方式實現(xiàn)。
compose :: (b -> c) -> (a -> b) -> a -> c compose f g x = f (g x)
通過 Haskell 強大的類型簽名中,大致可以推出compose函數(shù)的作用。b -> c 代表了一個從b類到c類的映射函數(shù),a -> b也是一樣,compose函數(shù)接受兩個函數(shù)f和g,返回一個新的函數(shù)h,h函數(shù)表達了從a類到b類再到c類的映射。
舉個例子,我們有sum函數(shù) —— 給列表求和,odd函數(shù) —— 判斷數(shù)字是否是奇數(shù)。(簡單起見,給他們的類型簽名并不準確,但足夠簡單)
odd :: Int -> Bool sum :: [Int] -> Int sumIsOdd :: [Int] -> Bool sumIsOdd = compose odd sum sumIsOdd [1,2,34,5]
sumIsOdd函數(shù)組合了求和與判斷奇數(shù)兩個函數(shù),他并沒實現(xiàn)具體的功能,而是通過一種通俗的組合實現(xiàn)了將單一的函數(shù)轉(zhuǎn)化成稍微復雜的函數(shù),從而達到功能上的擴充,我想這就是組合的魅力,也是函數(shù)式的魅力之一吧。
JavaScript 的組合JavaScript是一門表現(xiàn)力極強的語言,除了本質(zhì)上對面向?qū)ο蟮闹С?,對函?shù)式編程的支持也絲毫不弱,組合函數(shù)實現(xiàn)起來雖然復雜,但是也未必不可行,而且相對于Haskell的晦澀,JavaScript更加簡單一點
const odd = x => x % 2 !== 0; const sum = args => args.reduce((a, b) => a + b); const compose = (...fs) => arg => fs.reduceRight((f, g) => g.call(null, f), arg);
借助ES6的箭頭函數(shù)實現(xiàn)起來得心應手,可見即便是JavaScript這種以面向?qū)ο笏枷朐O計的語言也希望在函數(shù)式編程上面能有所建樹。
順帶一提,對數(shù)組擴充的map、filter、reduce等函數(shù),也是JavaScript對函數(shù)式編程的支持,雖然只是利用while循環(huán)做的語法糖,效率也不如while循環(huán),但是在JavaScript的語境中,很少對效率有極高的要求,所以從語義上來講,我更傾向用函數(shù)式的方式解決純數(shù)據(jù)的問題。
小結(jié)函數(shù)式編程隨著多核CPU的發(fā)展,開始再次出現(xiàn)在我們的視野中,有時候也會擔心過于吹捧函數(shù)式,反而落入俗套。仔細想想,編程范式并不是一枝獨秀的世界,而是百家爭鳴的,各有擅長的領(lǐng)域。當然在一些環(huán)境下兩者也是能夠共存的,甚至兩者同時帶來的收益可能更加可觀呢。
說回組合,其實我自己也只是一個半吊子,也需要不斷的學習才能對組合有一個更加清晰的認識,而不是拘泥于語言,在實際生產(chǎn)中分化和組合也實在太重要了,并不是一兩個函數(shù)能夠概括的,現(xiàn)在的也我只能以這種簡單的方式作了解了。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/97274.html
摘要:函數(shù)式編程逐漸被邊緣化,被拋棄到學術(shù)界和非主流的場外。組合式編程的重新崛起年左右,有個巨大的變化爆發(fā)了。人們開始逐漸在私下里談論函數(shù)式編程。箭頭函數(shù)對于函數(shù)式編程的爆發(fā)起到了推動劑的作用。現(xiàn)在很少看到那種不用函數(shù)式編程的大型應用了。 showImg(https://segmentfault.com/img/remote/1460000009036867?w=800&h=364); 本...
摘要:組合的概念是非常直觀的,并不是函數(shù)式編程獨有的,在我們生活中或者前端開發(fā)中處處可見。其實我們函數(shù)式編程里面的組合也是類似,函數(shù)組合就是一種將已被分解的簡單任務組織成復雜的整體過程。在函數(shù)式編程的世界中,有這樣一種很流行的編程風格。 JavaScript函數(shù)式編程,真香之認識函數(shù)式編程(一) 該系列文章不是針對前端新手,需要有一定的編程經(jīng)驗,而且了解 JavaScript 里面作用域,閉...
摘要:函數(shù)組合是函數(shù)式編程中非常重要的思想,它的實現(xiàn)的思路也沒有特別復雜。前者從左向右組合函數(shù),后者方向相反。下面就是一個最簡單的可以組合兩個函數(shù)的在實際應用中,只能組合兩個函數(shù)的組合函數(shù)顯然不能滿足要求,我們需要可以組合任意個函數(shù)的組合函數(shù)。 函數(shù)組合是函數(shù)式編程中非常重要的思想,它的實現(xiàn)的思路也沒有特別復雜。有兩種函數(shù)組合的方式,一種是pipe,另一種是compose。前者從左向右組合函...
摘要:函數(shù)式編程,一看這個詞,簡直就是學院派的典范。所以這期周刊,我們就重點引入的函數(shù)式編程,淺入淺出,一窺函數(shù)式編程的思想,可能讓你對編程語言的理解更加融會貫通一些。但從根本上來說,函數(shù)式編程就是關(guān)于如使用通用的可復用函數(shù)進行組合編程。 showImg(https://segmentfault.com/img/bVGQuc); 函數(shù)式編程(Functional Programming),一...
摘要:可當我們進行函數(shù)式編程時,這樣的方式會遇到困難,難點在于如何停止。而在函數(shù)式編程中,數(shù)據(jù)在管道中流動,上一個函數(shù)的返回值會傳給下一個函數(shù),除非報錯,事先寫好的流程是停不下來的。 以下代碼會用到函數(shù)組合函數(shù)compose,只要知道compose是干什么的就足夠了,如果好奇具體的實現(xiàn),可以看《JavaScript函數(shù)式編程之函數(shù)組合函數(shù)compose和pipe的實現(xiàn)》 在寫命令式的代碼時,...
閱讀 968·2021-09-03 10:42
閱讀 1557·2019-08-30 15:56
閱讀 1492·2019-08-29 17:27
閱讀 919·2019-08-29 15:25
閱讀 3232·2019-08-26 18:27
閱讀 2533·2019-08-26 13:41
閱讀 1944·2019-08-26 10:39
閱讀 1635·2019-08-23 18:36