Java 平台長期屬於物件導向領域,但近年函數式程式設計趨勢興起。Scala 作為 JVM 上融合雙範式的語言,保留 Java 生態相容性,引入 Haskell/ML 的函數核心原則。本文為系列首篇,說明為何學習 Scala、快速上手安裝與核心函數概念實戰。
Java 語言設計於 20 年前(單核、撥號上網、繼承為王時代)。摩爾定律撞牆催生多核 CPU,並發程式設計成為硬需求。傳統 Java 靠鎖與可變狀態應對並發,複雜且易出錯。學術界推出許多新語言,但遷移平台風險極大。Scala 精準切入此痛點:
官網下載 scala-2.6.1-final,設定 SCALA_HOME 並加入 PATH。驗證:scalac -version。
object HelloWorld {
def main(args: Array[String]): Unit = {
System.out.println("Hello, Scala!")
}
}
編譯 scalac Hello.scala,執行 scala HelloWorld 或 java -cp $SCALA_HOME/lib/scala-library.jar:. HelloWorld。
object 關鍵字宣告單例,無需 staticname: Type 形式,泛型用方括號 Array[String]Unit 等同 Java void,函數最後一行表達式為隱式回傳值函數為一級公民,可賦值變數、作為參數傳遞、從函數回傳。以定時器為例演進:
object Timer {
def oncePerSecond(): Unit = {
while (true) {
println("Time flies...")
Thread.sleep(1000)
}
}
def main(args: Array[String]): Unit = oncePerSecond()
}
def oncePerSecond(callback: () => Unit): Unit = {
while (true) { callback(); Thread.sleep(1000) }
}
def timeFlies(): Unit = println("Time flies...")
oncePerSecond(timeFlies) // 傳遞具名函數
() => Unit 表示「無參數、回傳 Unit」的函數型別。
oncePerSecond(() => println("Time flies... oh, you get the idea."))
無需預先定義具名函數,行為內嵌於呼叫點。
def periodicCall(seconds: Int, callback: () => Unit): Unit = {
while (true) { callback(); Thread.sleep(seconds * 1000) }
}
periodicCall(1, () => println("Time flies..."))
這是函數式核心模式:高階抽象函數 + 程式碼塊參數化,替代傳統迴圈內嵌邏輯。
Scala 集合提供豐富高階函數。範例:找出所有 Scala 程式設計師並加薪:
val programmers = Array(
new Person("Ted", "Neward", 37, 50000, Array("C++", "Java", "Scala", ...)),
new Person("Amanda", "Laucher", 27, 45000, Array("C#", "F#", "Java", "Scala")),
...
)
val scalaProgs = programmers.filter(p => p.skills.contains("Scala"))
scalaProgs.foreach(p => p.salary += 5000)
或用 map 產生新集合保持不可變:
def raise(p: Person) = new Person(p.firstName, p.lastName, p.age, p.salary + 5000, p.skills)
val raised = scalaProgs.map(raise)
對比 Java 迭代器寫法,Scala 版本極度簡潔且無副作用風險。
Java 需 String msg = "...",Scala 編譯器自動推斷:val msg = "..."。複雜泛型情境下同樣適用,大幅減少冗餘型別宣告。
Scala 讓 Java 開發者在熟悉的 JVM 上體驗函數式思維:熟悉的核心類庫、全新的分解問題方式。本文僅入門,後續將深入類別特性、特質、模式比對、DSL 建構等進階主題。現在,享受函數式程式設計的樂趣吧!