1. 程式人生 > >【程式語言】SCALA

【程式語言】SCALA

Scala是一門多正規化的程式語言,一種類似java的程式語言 [1] ,設計初衷是實現可伸縮的語言 [2] 、並整合面向物件程式設計和函數語言程式設計的各種特性。
Scala程式語言抓住了很多開發者的眼球。如果你粗略瀏覽Scala的網站,你會覺得Scala是一種純粹的面向物件程式語言,而又無縫地結合了指令式程式設計和函數語言程式設計風格。Christopher Diggins認為:
不太久之前程式語言還可以毫無疑意地歸類成“命令式”或者“函式式”或者“面向物件”。Scala代表了一個新的語言品種,它抹平了這些人為劃分的界限。
根據David Rupp在部落格中的說法,Scala可能是下一代Java。這麼高的評價讓人不禁想看看它到底是什麼東西。
Scala有幾項關鍵特性表明了它的面向物件的本質。例如,Scala中的每個值都是一個物件,包括基本資料型別(即布林值、數字等)在內,連函式也是物件。另外,類可以被子類化,而且Scala還提供了基於mixin的組合(mixin-based composition)。
與只支援單繼承的語言相比,Scala具有更廣泛意義上的類重用。Scala允許定義新類的時候重用“一個類中新增的成員定義(即相較於其父類的差異之處)”。Scala稱之為mixin類組合。
Scala還包含了若干函式式語言的關鍵概念,包括高階函式(Higher-Order Function)、區域性套用(Currying)、巢狀函式(Nested Function)、序列解讀(Sequence Comprehensions)等等。
Scala是靜態型別的,這就允許它提供泛型類、內部類、甚至多型方法(Polymorphic Method)。另外值得一提的是,Scala被特意設計成能夠與Java和.NET互操作。Scala當前版本還不能在.NET上執行(雖然上一版可以-_-b),但按照計劃將來可以在.NET上執行。
Scala可以與Java互操作。它用scalac這個編譯器把原始檔編譯成Java的class檔案(即在JVM上執行的位元組碼)。你可以從Scala中呼叫所有的Java類庫,也同樣可以從Java應用程式中呼叫Scala的程式碼。用David Rupp的話來說,
它也可以訪問現存的數之不盡的Java類庫,這讓(潛在地)遷移到Scala更加容易。
這讓Scala得以使用為Java1.4、5.0或者6.0編寫的巨量的Java類庫和框架,Scala會經常性地針對這幾個版本的Java進行測試。Scala可能也可以在更早版本的Java上執行,但沒有經過正式的測試。Scala以BSD許可釋出,並且數年前就已經被認為相當穩定了。
說了這麼多,我們還沒有回答一個問題:“為什麼我要使用Scala?”Scala的設計始終貫穿著一個理念:
創造一種更好地支援元件的語言。(《The Scala Programming Language》,Donna Malayeri)
也就是說軟體應該由可重用的部件構造而成。Scala旨在提供一種程式語言,能夠統一和一般化分別來自面向物件和函式式兩種不同風格的關鍵概念。
藉著這個目標與設計,Scala得以提供一些出眾的特性,包括:

  • 面向物件風格
  • 函式式風格
  • 更高層的併發模型
    Scala把Erlang風格的基於actor的併發帶進了JVM。開發者可以利用Scala的actor模型在JVM上設計具伸縮性的併發應用程式,它會自動獲得多核心處理器帶來的優勢,而不必依照複雜的Java執行緒模型來編寫程式。
  • 輕量級的函式語法
    o 高階
    o 巢狀
    o 區域性套用(Currying)
    o 匿名
  • 與XML整合
    o 可在Scala程式中直接書寫XML
    o 可將XML轉換成Scala類
  • 與Java無縫地互操作
    Scala的風格和特性已經吸引了大量的開發者,比如Debasish Ghosh就覺得:
    我已經把玩了Scala好一陣子,可以說我絕對享受這個語言的創新之處。
    總而言之,Scala是一種函式式面嚮物件語言,它融匯了許多前所未有的特性,而同時又運行於JVM之上。隨著開發者對Scala的興趣日增,以及越來越多的工具支援,無疑Scala語言將成為你手上一件必不可少的工具。
    Scala與Groovy的對比
    一篇名為“Scala,Groovy的殺手? ”的部落格對Scala和Groovy進行了對比:
    Scala和Groovy之間的核心區別在於前者是靜態型別的。有些人可能爭辯說這使得達到指令碼化目標變得更加複雜了,而指令碼化正是Groovy的動機。然而,Scala有完整的體系特徵,這使Groovy看上去更像個玩具。比如,Scala有“sequence comprehensions”。該要素導致對演算法的表述非常緊湊和強大。
    Scala還有更多被證明是非常有用的特性,如巢狀類,currying和代數型別模式匹配。它還支援類似於JDK1.5所增加的泛型和註解。這些還都只是冰山一角。
    之後,Derek Young撰文“Scala對比Groovy:靜態型別是效能的關鍵”。在文中他舉了一個實際的例子,試圖說明針對同樣的演算法,Scala的效能遠高於Groovy。
    然而,Scala並不是盡善盡美的,它也有一些明顯的缺陷。Rick Hightower在發表的一篇部落格中,尖銳地批評了Scala的語法問題:
    Scala並不是更好的選擇。在閱讀了Scala的文件之後,我的想法是:雖然這種語言的特性聽起來挺好,但是語法卻讓我想放棄。為什麼事情非要為了不同而不同?Scala讓Groovy看起來比以前更加美味可口。
    憎恨是個很強烈的詞。我恨Scala的語法。請不要再推進這種語法了。……Scala有好的思想嗎?有。借用過來就行了……
    總而言之,Scala看起來像下一個被過度宣傳的語言。只需要把其精華引入到Groovy中,然後扔掉那些糟糕的語法。我最喜歡的Scala特性是推理型別和強型別。C#3.0也有這些。(我不用C#,不見得我不喜歡它的一些特性。)
    Rick Hightower還建議Sun應該在Groovy上進行投資,而不是對JRuby作無謂的投資。
    Groovy更像Java,更容易上手,語法也讓開發者不反感。為什麼Sun在JRuby上投那麼多錢呢?
    投資應該給Groovy。這樣瞭解Java的開發者可以更快地學習Groovy,而且如果有工具支援他們,那麼就更可能這樣做。
    為了說明Sun投資在Ruby上的不明智,Rick Hightower還引用了一幅統計圖表來說明企業採用Ruby的趨勢還是比較低的:

圖1
另外,無論是Ruby、Scala還是Groovy都有對應的Web框架,且對應的框架都是用各自對應的語言編寫的。這些框架分別是Rails、Lift和Grails。儘管Lift和Grails中的許多東西都從Rails借鑑來的,但是Grails對其他已有Java技術框架進行了很好的繼承,這無疑會保護使用者或廠商在這方面的已有投資。Grails框架參考文件中這樣描述:
Grails構建在這些概念之上,並且顯著地減少了在Java平臺上構建Web應用的複雜程度。不同的是,這些是建立在已確立的如Spring和Hibernate這樣的Java技術之上的。
Scala和Groovy兩種語言都在快速發展的過程中。就情況來看,Groovy的優勢在於易用性以及與Java無縫銜接,Scala的優勢在於效能和一些高階特性,如果在發展過程中兩者能互相借鑑對方的優點來充實自身,對開發者來講無疑是福音。正如第一篇所引用的部落格作者最後提到的那樣:
大家並不想看到一場殊死鬥爭,而是想看到更注重實效思想的Groovy團隊能與更具有學術思想的Scala團隊一起合作,製作出一門既強大又易用的語言。
你會將賭注押在誰身上呢?
Scala 發音為 /ˈskɑːlə, ˈskeɪlə/)是一種多正規化的程式語言,設計意圖是要整合面向物件程式設計和函數語言程式設計的各種特性。
技巧
1、不要陷入C++一樣的、不斷膨脹的問題裡,留下太多的選擇,且沒有清晰的最佳實踐。這導致每個人都在選擇不同的子集。要提供適應的指導。
2、記住,反對不良的設計功能與增加新功能同等重要——這很殘酷。
3、考慮拆分語言為生產環境建立可行的標準。為學術世界節省成本是一個明智的選擇。迎合企業的需要,獲得更大的採用。
4、庫的編寫者應該看看Java API,確認是否應該有功能呼叫或結構化功能,為了更好的閱讀。不要為了流動性在跳躍太大來與Ruby競爭。
5、最後,當人們提出的建設性的批評時,不要感到失望。如果同樣的報怨不斷出現,那就說明應該重視一下。 [3]
平臺和許可證
Scala運行於Java平臺(Java虛擬機器),併兼容現有的Java程式。它也能運行於Java ME, CLDC(Java Platform, Micro Edition Connected Limited Device Configuration)上。還有另一.NET平臺的實現,不過該版本更新有些滯後。
Scala的編譯模型(獨立編譯,動態類載入)與Java和C#一樣,所以Scala程式碼可以呼叫Java類庫(對於.NET實現則可呼叫.NET類庫) 。
Scala包中包含了編譯器和類庫,以BSD許可證釋出。
發展歷史編輯
聯邦理工學院洛桑(EPFL)的Martin Odersky於2001年基於Funnel的工作開始設計Scala。Funnel是把函數語言程式設計思想和Petri網相結合的一種程式語言。Odersky先前的工作是Generic Java和javac(Sun Java編譯器)。Java平臺的Scala於2003年底/2004年初發布。.NET平臺的Scala釋出於2004年6月。該語言第二個版本,v2.0,釋出於2006年3月。
截至2009年9月,最新版本是版本2.7.6 。Scala 2.8預計的特性包括重寫的Scala類庫(Scala collections library)、方法的命名引數和預設引數、包物件(package object),以及Continuation.
2009年4月,Twitter宣佈他們已經把大部分後端程式從Ruby遷移到Scala,其餘部分也打算要遷移。此外, Wattzon已經公開宣稱,其整個平臺都已經是基於Scala基礎設施編寫的。
特性
面向物件特性
Scala是一種純面向物件的語言,每一個值都是物件。物件的資料型別以及行為由類和特徵(Trait)描述。類抽象機制的擴充套件有兩種途徑。一種途徑是子類繼承,另一種途徑是靈活的混入(Mixin)機制。這兩種途徑能避免多重繼承的種種問題。 [4]
函數語言程式設計
Scala也是一種函式式語言,其函式也能當成值來使用。Scala提供了輕量級的語法用以定義匿名函式,支援高階函式,允許巢狀多層函式,並支援柯里化 。Scala的Case Class及其內建的模式匹配相當於函數語言程式設計語言中常用的代數型別(Algebraic Type)。 [4]
更進一步,程式設計師可以利用Scala的模式匹配,編寫類似正則表示式的程式碼處理XML資料。在這些情形中,順序容器的推導式(comprehension)功能對編寫公式化查詢非常有用。
由於JVM不支援尾部遞迴,Scala也不能完全支援尾部遞迴優化。不過,在簡單的情況下,Scala編譯器可以把尾部遞迴優化成迴圈。
以下程式碼以函式式風格實現了快速排序演算法,可以與Erlang快速排序的例子做個比較:
def qsort(list: List[Int]): List[Int]=
list match{
case Nil => Nil
case pivot::tail =>
qsort(for(i <- tail if i < pivot)yield i)::: pivot :: qsort(for(i <- tail if i >= pivot)yield i)
}
靜態型別
Scala是具備型別系統,通過編譯時的檢查,保證程式碼的安全性和一致性。型別系統具體支援以下特性:
泛型類,型變註釋(Variance Annotation),型別繼承結構的上限和下限,把類別和抽象型別作為物件成員,複合型別,引用自己時顯式指定型別,檢視,多型方法。 [4]
擴充套件性
Scala的設計承認一個事實,即在實踐中,某個領域特定的應用程式開發往往需要特定於該領域的語言擴充套件。Scala提供了許多獨特的語言機制,可以以庫的形式輕易無縫新增新的語言結構:
任何方法可用作字首或字尾操作符,可以根據預期型別自動構造閉包。聯合使用以上兩個特性,使你可以定義新的語句而無須擴充套件語法也無須使用巨集之類的超程式設計特性。 [4]
使用Scala的框架
Lift是一個開源的Web應用框架,旨在提供類似Ruby on Rails的東西。因為Lift使用了Scala,所以Lift應用程式可以使用所有的Java庫和Web容器。
測試
以下是測試Scala程式碼的一些方式:
ScalaTest ScalaCheck,類似於Haskell的QuickCheck的一個庫specs,一個用於Scala的行為驅動的開發工具庫JUnit內建的Scala庫SUnit已經不贊成使用,將會在2.8.0版中移除,見SUnit文件。
範例
以下是用Scala編寫的典型的Hello Scala中文程式:
object HelloScalachina extends Application { println(“Hello, Scala中文!”)}

object HelloScalachina {def main(args: Array[String]){ println(“Hello, Scala中文!”)}}
請注意它與Java的Hello Scala中文應用程式有哪些相似之處。一個顯著區別在於,Scala版的Hello Scala中文程式沒有把任何東西標記為static,而是用object 關鍵字建立了一個單件。
假設該程式儲存為HelloScalachina.scala檔案,接下來可以通過以下命令列進行編譯:

scalac HelloScalachina.scala
若要執行:
scala -classpath . HelloScalachina
這與編譯和執行Java的“Hello Scala中文”程式是不是很像呢?事實上,Scala的編譯和執行模型與Java是等效的,因而它也兼容於Java的構建工具,比如Ant.
直接使用Scala直譯器也可以執行該程式,使用選項-i (從檔案載入程式碼)和選項-e (若要執行額外的程式碼,就得實際執行HelloScalachina物件的方法)即可:
scala -i HelloScalachina.scala -e ‘HelloScalachina.main(null)’