在個人平常工做中,我身邊的開發者大可能是畢業於CS編程頂級院校好比MIT、CMU以及Chicago,他們初次涉及的語言是Haskell、Scheme及Lisp。他們認爲函數式編程是一種天然的、直觀的、美麗的且高效的編程樣式。但奇怪的是,我和個人同事並無爲Haskell、Scheme、Lisp、Clojure、Scala而編程,這個行業裏的絕大部分人都會使用Python、 Ruby、Java或C#等編程,由於它們用起來比較順手。但在Java中,函數式編程倒是低效且危險的。java
爲何函數式編程在Java中很危險呢?程序員
每隔幾個月,我都會在調試中發現問題,究其緣由最終可追溯到濫用函數的想法以及編程算法,更重要的緣由是這個虛擬機沒法建立這種編程樣式。算法
最近Bob Martin想出一個很好的例子並說明了緣由。Clojure (一個真正的函數式編程)返回到25整數列表:編程
此代碼運行和響應速度都很快,輸出結果:安全
如今,假設咱們想要在Java中重寫,若是咱們以Gosling的方式來編寫Java,那麼該代碼是簡單、快速且明顯的:函數式編程
可是,如今假設咱們讓它變得多功能性,在特定的假設範圍內重置上面的Clojure樣式:函數
嘗試運行吧,OK,從堆轉儲(Heap Dump)中恢復 ?性能
當Java輸出後,Clojure如何處理函數,使該函數可返回到每個int?學習
Clojure如同全部真正的函數語言(與Java不一樣)具有懶散賦值特性。它(指clojure)不會計算不被使用的值。它能夠遠離這個,由於Clojure不像Java,它是真正函數式語言,能夠假定變量不發生變異,使求值的順序變得可有可無。所以,Clojure能夠執行優化,可是Java編譯器卻不能——這就是爲何函數式編程在Java中是危險的緣由。由於,Java不是真正的函數式語言,JIT和javac沒法像在一個真正的函數式語言中積極且有效地優化函數構造對象,好比返回無窮個列表的標準函數計算,都是Java程序的死穴。這也是爲何函數式編程在Java中危險的緣由。優化
這裏,也許你會反對個人觀點,OK,你無須在Java中返回全部的整數列表(或者甚至是全部的ints);可是相信沒人作到這一點。
咱們來一塊兒看看比較現實的作法。這裏我再次使用遞歸來計算而不是循環:
開始運行!
很抱歉,堆棧溢出。這就是爲何在XOM中我當心翼翼地使用循環,即便遞歸的地方十分清楚也不使用遞歸。不然,精心配置XML文檔可能會形成XOM-using程序來轉儲核心。所以,避免在非函數式語言中進行大量遞歸,正如Java和C不只僅是性能需求,也是安全方面的要求。
寫在最後:
我不是說函數式編程很差,也不是說函數式編程低效,其實,我熱愛函數式編程。就像個人同事認爲函數式編程是天然、直觀且美麗的編程風格,但當它做爲一們語言好比爲Haskell從新設計時,Java中函數語句的性能Bug絕對能要了你的命。