記錄一次函數式編程語法糖拆解過程
使用Scala,不僅可以優雅地編寫簡潔的代碼,又能減少很多低級錯誤;能快速進行開發,又能保證系統性能、團隊協作和長期維護。
夏洛克ITOA系統,很多部分都使用Scala編寫。相關的技術心得就很多
摘 要
Scala是一種集合了面向對象以及面向函數式的基於jvm的編程語言,所以編寫scala代碼,既可以完全類似java一樣的風格,也可以寫出基於函數式的天馬行空的『優雅』的代碼,spark裡面rdd相關的代碼就是scala函數式編程的極致體現,真正做到了到最後一刻才會計算的延遲載入。
不過相比面向對象的風格,函數式編程風格的代碼有時會難以理解,實際的執行順序難以琢磨,下面是一個我最近看過的一個例子,簡單記錄一下。
解讀過程
代碼如下,入口在方法def imperativelyComplete,這個方法的主要目的是基於akka http的RequestContext進行封裝,把當前http請求上下文傳給其他地方進行處理,不過這個不是本文的重點,本文的重點是imperativelyComplete方法的定義,大家可以先自行觀看幾秒鐘。
比較明顯可以看出的是,這個方法的輸入參數是一個函數(輸入為ImperativeRequestContext類型,沒有返回值),這種定義方法還是比較多見的,比如Loan Pattern
接著再看這個方法的方法體,會有一個類似類定義裡面的self annotation的 ctx:RequestContext,看到這裡有些同學可能就比較頭暈了,這個ctx是哪來的??
別著急,都知道scala糖多,我們可以藉助scalac這個工具,來看看去糖之後的樣子,為了去除掉不必要的依賴,讓scalac可以編譯通過,我寫了一個類似的例子(Test.scala):
執行scalar -Xprint:typer Test.scala
下面這個就是imperativelyComplete方法去糖之後的樣子,可以看到這個方法的輸入參數是一個函數,並且返回值也是一個函數,並且作為返回值的這個函數的輸入參數為Req類型
看到這裡就完全明白了。最開始例子裡面的返回值也是一個函數:RequestContext => Future[RouteResult],只是目前的這種寫法不是太明顯,如果能像去糖後把返回值的結構清晰的定義出來,就一目了然了。如果我們看一下akka http庫裡面關於路由Route的定義,就會發現兩者是一致的,所以在akka http的路由裡面用imperativelyComplete這個方法,才可以編譯通過。
結 論
函數式編程風格的代碼有時確實比較難讀懂,特別是在scala當中,結合implicit這種特性,就靈活度更大。如果一時看不懂,可以試著換種角度去理解(本文中我們在探尋ctx是哪來的,沒想到它卻是返回值的一部分),當然更推薦使用scalac這個工具來一探糖背後的組成。
夏洛克ITOA
Make Data Think
人工智慧 機器學習 IT運維
![](https://pic.pimg.tw/zzuyanan/1488615166-1259157397.png)
![](https://pic.pimg.tw/zzuyanan/1482887990-2595557020.jpg)
TAG:夏洛克ITOA |