Scala: 感覺像動態的靜態語言
Weblogs Forum - Scala: The Static Language that Feels Dynamic
著名的"Thinking in Java"作者Bruce Eckel 在artima.com寫了這篇Scala入門篇(banq:artima的論壇和Jdon的論壇都源於同一個宗主Jive,所以你覺得兩者介面很象)。
下面大概意譯一下Bruce Eckel這篇文章:
Bruce Eckel 認為scala雖然是靜態語言,但感覺非常像Python,
(Bruce Eckel用語很感性,不象Thinking,而象feeling)。
val是不可變數,這樣能夠使得併發編碼更容易一些(var也有變數的).這裡沒有必要在b之前象Java那樣宣告一下型別,因為scala能夠分辨出型別。
println列印輸出不必使用類似Java的System.out了,類中欄位預設是public的,這樣我們可以使用b.squareFeet直接訪問其類中欄位。當然你也可以設定private。
這段和上面區別是b.feet, feet能夠自動成為類的欄位。
這段程式碼主要是開始的case class ,引數自動成為欄位,引數之前也不用加val了。
scala中使用->來表示map的鍵和值。
展示了extends繼承,但是注意extends後面的父類寫法。
traits是將行為混合在一起,類似過去的AOP等,被認為用來實現DCI架構較好的語言方式,這裡的trait非常類似Java中的介面,但比介面要豐富,可以自己定義方法occupants,其def是用來定義方法名稱的,等於號後面是方法體。
def occupants() = { 1 }表示返回值int型別1,如果要更加規範如下:
def occupants(): Int = { 1 }
注意occupants已經成為House的一部分,這就是traits的mixin力量,而且這個mixin的效能要比Java好多。
以上是簡單的語法。
透過下面語法可以輸出列印:
for(n <- v) {
println(n)
}
注意:<- 前面的n能夠得到v集合中每個值。
還有更簡單的:v.foreach(println) (Java中引數一般是變數,不會是方法等,這裡是方法println)
別看這麼簡單,它是利用的函式程式設計的優點,實際是一個匿名函式,完整的基本形式:
=>意味著:將左邊的引數應用到右邊的程式碼中。
另外一個匿名函式案例:
(x:Int, y:Double) => x * y
之前的foreach ,實際完整的如下:
v.foreach((n:Double) => println(n))
通常情況下,scala能夠看到v中的值類似是Double,因此可以簡化如下:
v.foreach((n) => println(n))
如果你只有一個引數,忽略括號
v.foreach(n => println(n))
如果你只有一個引數,還可以將節省引數,用下劃線替代:
v.foreach(println(_))
最後,如果函式方法只是呼叫一個其他方法,而且那個方法只使用一個引數,最後可以成為:
v.foreach(println)
可惜,foreach 有副作用,它不能返回任何值,大部分情況我們需要操作一個collection,並且返回值,然後,在這個返回結果上做一些操作(map/reduce),那麼使用map,注意它不是資料結構Map。
v.map(n => n * 2)
將v中每個值乘以2,然後返回結果:
Vector(2.2, 4.4, 6.6, 8.8)
簡寫如下:
v.map(_ * 2)
還有其他操作方法:
v.permutations 是產生一個遍歷指標iterator
v.permutations.foreach(println).
另外有用功能是zip,可以把兩個集合合併在一起:
Vector(1,2,3).zip(Vector(4,5,6))
結果是:
Vector((1,4), (2,5), (3,6))
v.zip(v.map(_ * 2))結果是:
Vector((1.1,2.2), (2.2,4.4), (3.3,6.6), (4.4,8.8))
匿名函式非常簡單易用,但是如果你覺得難以理解,那麼可以使用標準函式:
def timesTwo(d: Double) = d * 2
v.zip(v.map(_ * 2))就變為:v.zip(v.map(timesTwo))
(banq注:在Java中大概要使用visitor模式來實現,複雜些)
match語法類似Java的switch 。但是break不是必須的。
case class對於模式匹配特別有用,因為可以分解它。Any是所有物件的根class,類似Java中的primitive型別,
(banq注:看到這段感覺很象Java的執行緒類,是不是可以改造一下呢)
act()方法是一個自動的 match方式,loop{ react{看上去怪,但是scala的關鍵,開始你能使用loop來開啟郵箱訊息的match狀態,它實際是一個協調的多工,每個任務做點事情然後放棄控制權,讓下一個任務,這種方式好處沒有共享記憶體,因此可以擴充伸縮,可以達數百萬個任務。
注意class Benny開始兩行:
this ! Hop
start()
scala不能在方法內進行物件初始化,放到方法之外,類中,!感嘆號是傳送訊息,然後呼叫start()開始訊息不斷迴圈檢查。
以上是Scala主要特徵,本人看下來感覺是簡單些,特別在瞭解了函式程式設計和Actors這兩個主要程式設計正規化和思想,我在Jdon其他帖子花過大量時間來討論,有人感覺Scala複雜,可能是因為開始被誤導?實際Scala比較簡單強大。
著名的"Thinking in Java"作者Bruce Eckel 在artima.com寫了這篇Scala入門篇(banq:artima的論壇和Jdon的論壇都源於同一個宗主Jive,所以你覺得兩者介面很象)。
下面大概意譯一下Bruce Eckel這篇文章:
Bruce Eckel 認為scala雖然是靜態語言,但感覺非常像Python,
(Bruce Eckel用語很感性,不象Thinking,而象feeling)。
class Building val b = new Building <p class="indent"> |
val是不可變數,這樣能夠使得併發編碼更容易一些(var也有變數的).這裡沒有必要在b之前象Java那樣宣告一下型別,因為scala能夠分辨出型別。
class Building(feet: Int) { val squareFeet = feet } val b = new Building(100) println(b.squareFeet) <p class="indent"> |
println列印輸出不必使用類似Java的System.out了,類中欄位預設是public的,這樣我們可以使用b.squareFeet直接訪問其類中欄位。當然你也可以設定private。
class Building(val feet: Int) val b = new Building(100) println(b.feet) <p class="indent"> |
這段和上面區別是b.feet, feet能夠自動成為類的欄位。
case class Building(feet: Int) val b = Building(100) println(b) // Result: Building(100) <p class="indent"> |
這段程式碼主要是開始的case class ,引數自動成為欄位,引數之前也不用加val了。
val m = Map(Building(5000) -> "Big", Building(900) -> "Small", Building(2500) -> "Medium") m(Building(900)) // Result: Small <p class="indent"> |
scala中使用->來表示map的鍵和值。
class House(feet: Int) extends Building(feet) val h = new House(100) println(h.feet) // Result: 100 <p class="indent"> |
展示了extends繼承,但是注意extends後面的父類寫法。
trait Bathroom trait Kitchen trait Bedroom { def occupants() = { 1 } } class House(feet: Int) extends Building(feet) with Bathroom with Kitchen with Bedroom var h = new House(100 val o = h.occupants() val feet = h.feet <p class="indent"> |
traits是將行為混合在一起,類似過去的AOP等,被認為用來實現DCI架構較好的語言方式,這裡的trait非常類似Java中的介面,但比介面要豐富,可以自己定義方法occupants,其def是用來定義方法名稱的,等於號後面是方法體。
def occupants() = { 1 }表示返回值int型別1,如果要更加規範如下:
def occupants(): Int = { 1 }
注意occupants已經成為House的一部分,這就是traits的mixin力量,而且這個mixin的效能要比Java好多。
以上是簡單的語法。
函式程式設計方式functional programming :
比如我們有一個集合資料:
val v = Vector(1.1, 2.2, 3.3, 4.4) <p class="indent"> |
透過下面語法可以輸出列印:
for(n <- v) {
println(n)
}
注意:<- 前面的n能夠得到v集合中每個值。
還有更簡單的:v.foreach(println) (Java中引數一般是變數,不會是方法等,這裡是方法println)
別看這麼簡單,它是利用的函式程式設計的優點,實際是一個匿名函式,完整的基本形式:
( function parameters ) => function body <p class="indent"> |
=>意味著:將左邊的引數應用到右邊的程式碼中。
另外一個匿名函式案例:
(x:Int, y:Double) => x * y
之前的foreach ,實際完整的如下:
v.foreach((n:Double) => println(n))
通常情況下,scala能夠看到v中的值類似是Double,因此可以簡化如下:
v.foreach((n) => println(n))
如果你只有一個引數,忽略括號
v.foreach(n => println(n))
如果你只有一個引數,還可以將節省引數,用下劃線替代:
v.foreach(println(_))
最後,如果函式方法只是呼叫一個其他方法,而且那個方法只使用一個引數,最後可以成為:
v.foreach(println)
可惜,foreach 有副作用,它不能返回任何值,大部分情況我們需要操作一個collection,並且返回值,然後,在這個返回結果上做一些操作(map/reduce),那麼使用map,注意它不是資料結構Map。
v.map(n => n * 2)
將v中每個值乘以2,然後返回結果:
Vector(2.2, 4.4, 6.6, 8.8)
簡寫如下:
v.map(_ * 2)
還有其他操作方法:
v.reverse v.sum v.sorted v.min v.max v.size v.isEmpty <p class="indent"> |
v.permutations 是產生一個遍歷指標iterator
v.permutations.foreach(println).
另外有用功能是zip,可以把兩個集合合併在一起:
Vector(1,2,3).zip(Vector(4,5,6))
結果是:
Vector((1,4), (2,5), (3,6))
v.zip(v.map(_ * 2))結果是:
Vector((1.1,2.2), (2.2,4.4), (3.3,6.6), (4.4,8.8))
匿名函式非常簡單易用,但是如果你覺得難以理解,那麼可以使用標準函式:
def timesTwo(d: Double) = d * 2
v.zip(v.map(_ * 2))就變為:v.zip(v.map(timesTwo))
模式匹配
trait Color case class Red(saturation: Int) extends Color case class Green(saturation: Int) extends Color case class Blue(saturation: Int) extends Color def matcher(arg:Any): String = arg match { case "Chowder" => "Make with clams" case x: Int => "An Int with value " + x case Red(100) => "Red sat 100" case Green(s) => "Green sat " + s case c: Color => "Some Color: " + c case w: Any => "Whatever: " + w case _ => "Default, but Any captures all" } val v = Vector(1, "Chowder", Red(100), Green(50), Blue(0), 3.14) v.foreach(x => println(matcher(x))) <p class="indent"> |
(banq注:在Java中大概要使用visitor模式來實現,複雜些)
match語法類似Java的switch 。但是break不是必須的。
case class對於模式匹配特別有用,因為可以分解它。Any是所有物件的根class,類似Java中的primitive型別,
Actor併發模型
這個在jdon已經討論過多次,是一種Actor模型,透過非同步訊息通訊,可非同步併發。要比Java多執行緒模型併發效能更好,徹底杜絕了共享鎖。
// Bunnies.scala (Run as script: scala Bunnies.scala) case object Hop case object Stop case class Bunny(id: Int) extends scala.actors.Actor { this ! Hop // Constructor code start() // ditto def act() { loop { react { case Hop => print(this + " ") this ! Hop Thread.sleep(500) case Stop => println("Stopping " + this) exit() } } } } val bunnies = Range(0,10).map(new Bunny(_)) println("Press RETURN to quit") readLine bunnies.foreach(_ ! Stop) <p class="indent"> |
(banq注:看到這段感覺很象Java的執行緒類,是不是可以改造一下呢)
act()方法是一個自動的 match方式,loop{ react{看上去怪,但是scala的關鍵,開始你能使用loop來開啟郵箱訊息的match狀態,它實際是一個協調的多工,每個任務做點事情然後放棄控制權,讓下一個任務,這種方式好處沒有共享記憶體,因此可以擴充伸縮,可以達數百萬個任務。
注意class Benny開始兩行:
this ! Hop
start()
scala不能在方法內進行物件初始化,放到方法之外,類中,!感嘆號是傳送訊息,然後呼叫start()開始訊息不斷迴圈檢查。
以上是Scala主要特徵,本人看下來感覺是簡單些,特別在瞭解了函式程式設計和Actors這兩個主要程式設計正規化和思想,我在Jdon其他帖子花過大量時間來討論,有人感覺Scala複雜,可能是因為開始被誤導?實際Scala比較簡單強大。
相關文章
- 創業,你選擇靜態還是動態語言?創業
- 深入理解C語言----動態庫 & 靜態庫 & 連結C語言
- 英語的靜態句和動態句
- 什麼是靜態語言和動態語言。史上秒懂的大白話翻譯。
- 計算機語言:編譯型/解釋型、動態語言/靜態語言、強型別語言/弱型別語言計算機編譯型別
- 偽靜態、靜態和動態的區別
- C語言的本質(34)——靜態庫C語言
- Linux 依賴動態庫 / 靜態庫的動態態庫 / 靜態庫Linux
- Python 語言特性:編譯+解釋、動態型別語言、動態語言Python編譯型別
- C語言--靜態區域性變數C語言變數
- Go語言實現靜態伺服器Go伺服器
- 理解Javascript的動態語言特性JavaScript
- 概念區別 【編譯型語言與解釋型語言、動態型別語言與靜態型別語言、強型別語言與弱型別語言】編譯型別
- 字型,讓語言有了視覺形態視覺
- BootStrap的動態模態框及靜態模態框boot
- 靜態代理和動態代理
- 靜態路由和動態路由路由
- oracle 監聽 靜態 動態Oracle
- 靜態庫與動態庫
- 機器學習的靜態特徵和動態特徵機器學習特徵
- 淺談程式語言型別的強型別,弱型別,動態型別,靜態型別型別
- 動靜態庫
- 靜態SDRAM和動態SDRAM的區別
- Java中的靜態代理和動態代理Java
- 靜態代理、動態代理與Mybatis的理解MyBatis
- 靜態路由和動態路由的比較路由
- 動態庫和靜態庫的區別
- 動態語言與鴨子型別型別
- C語言動態呼叫庫(轉)C語言
- easyui 動態載入語言包UI
- C語言動態走迷宮C語言
- DEDE整站動態/靜態轉換
- ios靜態庫和動態庫iOS
- java靜態代理和動態代理Java
- 改造動態framework為靜態frameworkFramework
- 動態引數,靜態引數
- C語言編寫靜態連結庫及其使用C語言
- 不能被綜合的Verilog語言——非靜態迴圈