對象函數式編程 Scala簡史

本文概述了Scala語言誕生過程當中的各類軟件開發運動歷史的事件,當人們研究Scala時,發現這是一種給人印象深入的語言,可是因爲這種語言的功能特徵不斷的急速進化,致使除了一些本身研究的項目外,沒有其餘人再使用這種語言開發了。java

從前,有一種編程語言叫Scala,人們研究這種語言,發現這是一種給人印象深入的語言,有人說與Scala接觸的最大感覺就是Java如影相隨。這種語言看起來很美,但沒有人願意冒險把本身的職業生涯依賴於這種語言上,這個語言太年輕了,誰能保證它不會夭折?程序員

以後,發生了一些事情; Scala 長大了。 Twitter 宣佈他們用Scala語言替換了之前一些用Ruby開發的後端程序,而SAP也在使用這種語言,還有EDF等。 這消息迅速傳播開來,有許多新的程序開發者慕名而來,他們也都感受到這是一種使人印象深入的語言,同時,早期的這個語言的信徒也開始發現此語言已經鳳凰涅磐,讓他們眼睛一亮。web

他們如今看到的這種語言已是一個成熟的、急不可待的等人們使用它去大展宏圖的語言了。 隨着2.8版本的發佈,Scala 終於從少年進入了青年,能夠當之無愧的接受使人印象深入的讚譽了。編程

編程就是人生後端

程序語言在進化、在繁衍,產生不一樣的種族。很是相似於生命在早期地球的上的構成,編程語言最初是誕生於由CPU指令和數學概念混成的沸騰的高湯裏。 跟生命的發展不一樣的是,它們不須要泥土,可是它們也經歷着殘酷血腥的優勝劣汰、物競天擇過程,固然,你能夠把它們之間的戰爭想像成關於Tab鍵和Space鍵,關於括弧在程序中的地位問題上的戰爭 。設計模式

人們就像一個優秀的飼養員只喜歡挑選一個純種血統的良馬同樣選擇本身喜好的編程語言。 就像生物學上,人工育種必然存在不足,近親接二連三地繁殖、以此來保存某一血統的使人滿意的特性的作法必然潛藏基因缺陷的危險。數組

父母的結合產生的後代匯聚了其父母雙方各自不一樣的特徵,因此後代比前代更強大,同時父母各自的弱點也會被後代查明從而摒棄。 一樣的思想也被應用到了編程語言的世界裏,各類面向對象和麪向函數風格的概念相互融合給予了程序員們史無前例的能力和表達方式,Scala編程語言就是這樣的語言中的一員。服務器

我估計閱讀我這篇文章的大部分是Java程序員,因此在我詳細的解釋函數和對象如何交互以前我打算先介紹一些關於針對函數編程的概念。其實在網上已經有了不少徹底超出個人寫做水平的好教材,因此我願意儘可能簡單的介紹一下。閉包

什麼是函數?架構

數學裏,函數就是接受一個值(輸入值)然後使用它產生另一個值(輸出)的運算。 在很長的時間裏這個定義幾乎適用有全部任何的狀況,即便是如今,數學家們也只是在擴充這個定義裏的值的概念:複雜數值,矩陣,向量,座標(對稱座標和笛卡爾座標),四元數。.. 不少東西均可以被看成值,只要你用正確的方式去看待它。

這種狀況持續了好久,以後程序員出現了,以後計算機被髮明瞭。
一旦人們對計算機技術的重要性達成共識,而且使計算機技術逐步完善起來,程序員就開始用一種新的思想考慮他們了,好比:看着這計算機打印輸出的長河般一排排的三個字母組成的彙編程序碼,你不頭痛也不行。

若是他們能把那些序列碼按相同的功能分紅一組一組,給它們起個名稱,那麼他們將會有一種簡潔的方式去重複利用這些代碼,那麼之前花大量時間拼寫這些代碼的時間節省下來,終於有了去酒館的時間。 由於不少的程序員也都是數學家,由於不少他們的程序都是用來解決數學問題的,這就決定了函數的概念很是簡潔的迎合了這種給編程單元打包處理的行爲,今後第二代編程語言誕生了。

完美中的不足

這種革新,完美中有些不足。 針對函數,人們發現一個問題,就是常常須要它們一次處理多個輸入值,或,更使人沮喪的,多個輸出值。 幸運的是一些數學家解決了若是讓函數處理多個輸入值的問題,這種思想很早就被人採納了,人們按照這種思路想出來如何去返回多個輸出值(一般是把輸入值給抹去,替換我想要輸出的值)。 可是其餘的一些數學家(例如Haskell)並不喜歡多個輸入值的方式,他產生了一個新的觀點,用高階函數替代多個輸入值,函數能夠返回其它函數,或能夠用函數體看成函數參數,但這種作法很難實現,因此程序員起初都沒在乎這種觀點。

函數編程還有一個問題,就是它有反作用。 一個函數使用一個相同輸入值(例如讀一個文件)卻能夠每次都作出不一樣的事情,或者它能夠去作一些不專注的事情(例如處理返回一個值外還會向控制檯打印一行字)。 更糟糕的是,它會把本身的輸入值在使用以後改變其值! 對於那些想利用這些反作用的人來講,這是再好不過了,但是對於另外的一些數學家就不同了,他們不喜歡喝啤酒,但是還必需要把啤酒杯拿在手上。

因此程序裏的函數跟數學裏的函數是不一樣的。 人們給出了一個新的定義(不是很精確的):一個程序,或者一批指令,具備一個名稱,能夠選擇性的擁有一個或多個輸入值和輸出值,甚至同時具有多個輸入值和多個輸出值,同時還能作點額外的事情。

A reprive ahead of its time

天然,不少數學家並不高興函數被定義成這樣,因而一個新的語言品種被創造了出來,用來彌補其先天的不足,再一次的將它用一個穩固的理論架構肯定下來。函數體成爲第一類實體,而非之前的僅是一批代碼的別名。 這樣Haskell的高階函數的概念就能夠應用於設計開發軟件了。 編程語言的進化發展中人們愈來愈多的鼓勵使用常量值,這樣函數就不能把輸入值給能髒了。 人們實現了局部套用(Currying),開始使用數組結構,這樣函數終於又回到了只能接受一個輸入值和一個輸出值的紳士面貌。 一些有趣的方法被人們採用來限制那些討厭的反作用:若是這些反作用不能徹底避免的話,那就把它們規整起來專門找個地方放置它們。 這樣的語系被人們稱做爲函數式編程語言,由於它們把函數的概念迴歸到了其數學上的根源。 這個語系裏的語言包括有Lisp, Scheme, Caml, Erlang, F#, Clojure等。

做爲工程學上一個優秀的典範,函數式語言具備設計優良,易理解,高效,結構穩定等優勢。 與此同時,如同其餘Good Ideas?常常遇到的狀況同樣,很長的一段時間裏它們被主流團體所遺忘。 程序員們都很清楚爲何人們喜歡把函數放在首要位置; 人們須要把系統按單元功能劃分,相互不依賴,能夠在不一樣的地方重複使用它們。 這些願望就像癢癢須要撓的感受折磨着人們,因而面向對象的思惟今後誕生了並崛起了。

目前,函數式編程只是被人們當成一種業餘愛好,也被人們用在相關的演講和論文裏去靈巧的闡述一些新事物。 人們一般認爲函數式語言會比命令式語言運行的慢,但這種結論也許只有上帝知道,由於歷來沒有人用本身的方式證實過。 人們還認爲,儘管函數式語言看起來很是簡潔,適合小的程序和作演示用,但它們不太適合大規模的程序,像那些成百上千行的程序,若是用函數式語言來開發,幾乎是不可維護的。

重生

實際上,函數式語言並不僅是一種玩物。 跟隨着時代革新的大潮,它在地下醞釀了這麼多年,終於等到了這個世界但是接受它的這一天。 主流程序員們愈來愈多的認識到,函數式語言是如此的容易使用,而這一點在其它(面向對象)代碼是難以達到的。 就好比這個簡單的問題處理這個字符串隊列,將它們所有轉化成大寫後返回,用Java編寫卻有可能出錯。 由於偶爾人們會忽略掉這個隊列裏的第一個字串,由於他們從1開始計數,而不是0。有時候人們會發現這個隊列裏的字串不是按他們要求的部分轉化成大寫,而是所有大寫了,還有些時候程序會報出空指針異常。

逐漸的,人們開始討論起closures和continuations,爲的是讓他們的程序更加的強壯和可維護。 當時這些東西並非對象們所能具備的,因而增強型for循環被髮明瞭,還有匿名類,visitor模式,command 模式。 固然這些沒有一個能按照程序員們想象的那樣的完美,但這些東西仍是有用的,讓不少有問題的地方變得可維護了(即便這樣須要編排一些醜陋的模板式的代碼)。 時機已經到了人們改變思惟方式的時候了,函數式語言已經火燒眉毛的看到本身的宏大入場了。

讓人嫉妒的特性

經過Erlang語言,愛立信演示了函數式語言如何能應用於大規模系統的。 而其開發效率高,可維護性,可測試性都很好,特別是不易犯錯。 這纔是真正的函數式語言的面貌,感受比面嚮對象語言要成功的多。 愛立信的程序員們史無前例的有了充分的喝啤酒的空閒時間了。 生活變得輕鬆起來!

而在另外的陣營裏的程序員看待函數式語言有點想法,也有的嫉妒。 Java變得如此臃腫,並且,每個新出現的特徵都看起來是圍繞着它的模板代碼風格創造出來的。 即便是很小的程序,如今也要使用annotations,模板參數,和duplicate type declarations,大程序問題就更大了。 不幸中的不幸,關於如何往Java裏添加closures(閉包)功能的討論並不像早期預期的那樣順利,還有,Java bean裏的數不完的get/set方法實在是不能在忍受了。
有些事情必需要變了。

除了這些,Java還有一大堆的問題。 The Virtual Machine(虛擬機)是一個很是成熟的工具,通過了很好的優化,市場上隨處可見,從洗衣機,移動電話,到數不清的web服務器和桌面電腦裏都有它的身影。 Java系統在開源庫和框架方面已經發展的使人瞠目結舌繁華,在一些付費系統裏也火的不得了。 靠着Java這棵大樹,市面上已經處處都是由各類企業投資推進的數不清的團隊開發工做創造出的成功和成熟的java項目,若是由於一些小的語言特徵而放棄Java這一切基本是不可能的。

咱們一塊兒作蛋糕 也一塊兒吃

咱們全部作的事既要繼承Java全部目前的優質資產,同時也要使用函數式語言從新描繪新的編程語言版圖,Scala正好迎合了這種須要,儘管它有不少的競爭對手。 Pizza語言第一個出現的,但它跟今天的Scala比較起來更Scala當初的形式。

咱們所知的能在JVM上跑的語言大概有JavaFX, JRuby, Jython, Groovy 等。 大部分都有closures 和其餘的一些函數式語言具備的特徵,但在Java王國裏,這些新生事物並非那麼的血統純正,它們的特徵更像是外來移民,護照很新亮,但有異域口音。

動態語言的流行是無濟於事的; 類型能夠經過各類方法隱藏起來,讓人感到它的不存在,可是這樣很難編譯出原生的Java代碼了。 這是個很大的問題,特別是你寫出的對象須要拿到第三方類庫裏去處理時。 有時候各類語言之間很難交互,一般須要一個解釋器,就像JSR233 Scripting API 或 the Bean Scripting Framework 那樣。Scala卻有與生俱來的優點,它和Java的結合是如此的緊密,它能像本身自己的類型那樣處理Java類型,它並不像一個外來移民,而是一個僑胞,並且是有護照的公民。

你從外面看,Java和Scala編譯出來的代碼是如出一轍的,沒有區別,這有點讓人難以置信,但能夠明確的告訴你們,Scala最初就是這樣設計出來的。 當你把Scala看成一種函數式語言時,你會更驚奇的發現,它把面向對象和函數式的兩種風格以其優雅的方式徹底融合統一塊兒來。

正由於它和Java是如此緊密的聯繫,你能夠把Scala看成Java臨時的替代品,它絕對不會強制你用任何的函數式風格的代碼書寫。 它的類型引用,簡潔的屬性存取,以及帶有成員變量參數的構造函數,你幾乎能夠把它看成一種風格簡潔的Java。 除了上述的優勢外,咱們能夠稱讚Scala爲某些方便比Java面向對象更成功的語言:

一切皆爲對象,包括數值和函數

在Java中,方法不是對象,更別提基本數據類型了。 2.toString在Scala裏是一個合法的語句。它拋棄了靜態類成員,Java的這個問題能夠追溯到它所效仿的C++上,是個歷史錯誤。 C++自己就是個混合型的語言,它的設計目標就是要兼容過程式的C語言,同時也要支持對象結構。 靜態成員不是徹底的可面向對象,由於他們不能實現接口,以及向普通成員那樣的多形性和覆蓋、過載。 當你把一個對象看成參數傳入一個函數時,靜態成員是不可用的。

相反,Scala提供了singleton objects, 這樣這種問題就不存在了。 Scala裏新的companion概念可讓你使用singleton去訪問具備相同類名的實例上的一個有約束限定的成員,這樣你就能夠把靜態成員的權限複製出來。

類上全部的屬性都實現了behind-the-scenes,就像是個隱藏域,並且有針對它的一對Get和Set隱藏方法。 那些任何人均可以直接修改的內部屬性將再也不被容許公共訪問,在未來,虛擬類的概念將會在Scala裏出現,那樣後Scala對對象的支持將會有更驚人的表現。函數式編程對下面的特徵進行了支持:

◆對遞歸函數的尾調用(tail-call)優化

◆模式匹配

◆第一類函數和高級函數

◆局部函數(能夠接受任何輸入值)

◆局部套用(Currying)和函數局部應用

◆閉包

◆簡潔的聲明常量值的語法定義,很好的支持常量集合的類庫

◆continuations (scala 2.8 新增)

全部的這些都意味着什麼?

函數式編程已經證明了它的實力,快速增加的開發者人數是最好的證實,Scala向你們演示瞭如何在不犧牲面向對象思惟模式下接受函數式設計模式的概念。 它同時也向你們顯示了若是將這兩種風格的語言如何融合到一塊兒變成一個強壯豐滿的新語言,不帶任何的形式的勉強。

一旦你瞭解了基本語法並對閉包、第一類屬性、高階函數、traits,、immutable refs等概念有了認識,它的各類特色的相互結合會向你展現它更深層次的潛質。 語言生命裏的一些設計思想的選擇和肯定最終致使了一個增效做用,咱們認定這種新一代的對象-函數式的設計正是使Scala今天如此成功的關鍵。

相關文章
相關標籤/搜索