java8入門必備—函數(shù)式編程思維——函數(shù)式語言向語言和運行時讓渡控制權的途徑——迭代讓位于高階函數(shù)、閉包

構造一層又一層的抽象來處理(并隱藏)瑣碎的細節(jié)。隨著硬件能力的提高,將越來越多的任務轉嫁給語言和運行時。

函數(shù)式思維的好處之一,是能夠將低層次細節(jié)(如垃圾收集)的控制權移交給運行時,從而消弭了一大批注定會發(fā)生的程序錯誤。

不管層次高低,抽象的目的總是一樣的:讓開發(fā)者從繁瑣的運作細節(jié)里解脫出來,去解答問題中非重復性的那些方面。

函數(shù)式語言向語言和運行時讓渡控制權,讓開發(fā)者拋開負累,投入到更有意義的問題中去。

函數(shù)式語言向語言和運行時讓渡控制權的途徑——迭代讓位于高階函數(shù)

map等函數(shù)替換了迭代。如果能夠用高階函數(shù)把希望執(zhí)行的操作表達出來,語言將會把操作安排得更高效,甚至只要增加一行par修飾,就能夠讓操作并行化。

多線程代碼屬于最難編寫,最容易出錯,也最難調試的類別。只有卸下線程管理這份頭痛的差事,開發(fā)者才能少一些低層次的瑣碎操勞。

理解掌握的抽象層次永遠要比日常使用的抽象層次更深一層

程序員的工作效率依賴于抽象層。抽象隱藏了繁雜的細節(jié),只是有時候會連同重要的考慮因素一起隱藏掉。

開發(fā)者不應該拋開所有的責任,不去理解低層次抽象的來龍去脈。使用抽象必須清楚可能產(chǎn)生的連帶后果,理解底層的抽象細節(jié)才能寫出高性能的代碼。
當你掌握了背后的原理,才能把力量用在最正確的地方。

函數(shù)式語言向語言和運行時讓渡控制權的途徑——閉包

閉包(closure)是所有函數(shù)式語言都具備的一項平常特性。
閉包,實際上是一種特殊的函數(shù),它在暗地里綁定了函數(shù)內部引用的所有變量。這種函數(shù)(或方法)把它引用的所有東西都放在一個上下文里“包”了起來。

函數(shù)式語言向語言和運行時讓渡控制權的途徑——閉包——Groovy代碼演示閉包的創(chuàng)建和綁定


帶有amount參數(shù)的paidMore函數(shù),其返回值是一個以Employee實例為參數(shù)的代碼塊,或者叫閉包。類型聲明Employee可寫可不寫,這里寫出來順便起到文檔的作用。
給代碼塊傳入?yún)?shù)值100 000,并賦予isHighPaid的名稱,于是數(shù)值100 000就隨著這一步賦值操作,永久地和代碼塊綁定在一起了。以后有員工數(shù)據(jù)被代入這個代碼塊求解的時候,它就可以拿綁定的數(shù)值作為標準去評判員工的工資高低。

執(zhí)行閉包:



閉包在生成的時候,會把引用的變量全部圈到代碼塊的作用域里,封閉、包圍起來(故名閉包)。

閉包的每個實例都保有自己的一份變量取值,包括私有變量也是如此。可以創(chuàng)建paidMore閉包的另一個實例,給它綁定另外的數(shù)值(當然實例的名字也要另?。?br> 綁定另一個閉包:

閉包經(jīng)常被函數(shù)式語言和框架當作一種異地執(zhí)行的機制,用來傳遞待執(zhí)行的變換代碼,如map()之類的高階函數(shù)。在缺乏閉包特性的舊版Java平臺上,F(xiàn)unctional Java利用匿名內部類來模仿“真正的”閉包的某些行為,但語言的先天不足導致這種模仿是不徹底的。

函數(shù)式語言向語言和運行時讓渡控制權的途徑——閉包——原理


makeCounter()函數(shù)首先定義一個局部變量(local_variable),接著返回一個使用了該局部變量的代碼塊。
注意makeCounter()函數(shù)的返回類型是Closure,而不是一個單純的值。代碼塊的工作僅僅是遞增并返回其局部變量的值。方法中兩次明確寫出了return關鍵字,其實這兩個地方Groovy都允許省略。

調用代碼塊的時候用到了Groovy提供的語法糖衣,即在代碼塊變量名后直接跟一對圓括號的寫法(否則應該寫成c1.call())。

雖然局部變量不是在代碼塊里面定義的,但只要代碼塊引用了該變量,兩者就被綁定在一起,這種聯(lián)系在代碼塊實例的全部生命期內都一直保持著。
從實現(xiàn)的角度來說,代碼塊實例從它被創(chuàng)建的一刻起,就持有其作用域內一切事物的封閉副本。當代碼塊實例被垃圾收集的時候,它持有的引用也同時被回收。

創(chuàng)建一個閉包僅僅為了修改自身的內部狀態(tài),不是值得提倡的閉包用法,更常見的用法是綁定常量或者不可變的值。

函數(shù)式語言向語言和運行時讓渡控制權的途徑——閉包——Java8之前的模擬

Counter類還可以有別的一些寫法(比如寫成匿名的、泛型的,等等),但不管怎么做,都避免不了要自己去管理狀態(tài)。閉包在這里表現(xiàn)出來的函數(shù)式思維就是“讓運行時去管理狀態(tài)”。比起自己硬著頭皮去處理字段創(chuàng)建、呵護狀態(tài)(包括經(jīng)受多線程環(huán)境的嚴酷考驗)這些繁瑣的事務,還不如交出對狀態(tài)的控制權,讓語言和框架悄悄在背后幫我們管理好。

函數(shù)式語言向語言和運行時讓渡控制權的途徑——閉包——抓住上下文,而非狀態(tài)

讓語言去管理狀態(tài)。

閉包還是推遲執(zhí)行原則的絕佳樣板。把代碼綁定到閉包之后,可以推遲到適當?shù)臅r機再執(zhí)行閉包。這個特點在很多場合都能發(fā)揮作用。例如必要的變量和函數(shù)可能并不在定義時的作用域里,要到執(zhí)行的時候才準備好。那么把執(zhí)行上下文放在閉包里保留起來,就可以等到正確的時機再完成執(zhí)行。
命令式語言圍繞狀態(tài)來建立編程模型,參數(shù)傳遞是其典型特征。閉包作為一種對行為的建模手段,讓把代碼和上下文同時封裝在單一結構,也就是閉包本身里面,像傳統(tǒng)數(shù)據(jù)結構一樣可以傳遞到其他位置,然后在恰當?shù)臅r間和地點完成執(zhí)行。
抓住上下文,而非狀態(tài)。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • 86.復合 Cases 共享相同代碼塊的多個switch 分支 分支可以合并, 寫在分支后用逗號分開。如果任何模式...
    無灃閱讀 1,550評論 1 5
  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,534評論 19 139
  • 感謝社區(qū)中各位的大力支持,譯者再次奉上一點點福利:阿里云產(chǎn)品券,享受所有官網(wǎng)優(yōu)惠,并抽取幸運大獎:點擊這里領取 多...
    HetfieldJoe閱讀 1,098評論 0 11
  • 原文鏈接:https://github.com/EasyKotlin 值就是函數(shù),函數(shù)就是值。所有函數(shù)都消費函數(shù),...
    JackChen1024閱讀 6,326評論 1 17
  • 今晚 我又把明早的飯買好了 但常常 我對第二天的早餐沒有食欲 涼了 剩了 忘了 但我總是急著要買好明早的飯。
    倩何人換取閱讀 194評論 0 1

友情鏈接更多精彩內容