Scala 的控制結構雖語法似 Java,但本質全然不同——它們是**表達式**,擁有回傳值,且深度融合函數式特性。本文逐一剖析 if、while、for、try、match 的差異與威力。
Java 的 if-else 是語句,Scala 則是表達式,必須回傳同型別的值:
// Java:需用三元運算子達到同等效果
final String filename = options.contains("configFile")
? options.get("configFile") : "default.properties";
// Scala:自然表達式賦值給 val
val filename = if (options.contains("configFile"))
options.get("configFile")
else
"default.properties"
這使 val(不可變綁定)成為預設選擇,天然利於平行程式設計。
函數式語言偏好遞迴而非 while。以 QuickSort 為例:
// 命令式風格(可變狀態、難平行化)
def sort1(l: Int, r: Int) {
val pivot = xs((l + r) / 2)
var i = l; var j = r
while (i <= j) { ... }
}
// 函數式風格(不可變、遞迴、易推理)
def sort(xs: Array[Int]): Array[Int] =
if (xs.length <= 1) xs
else {
val pivot = xs(xs.length / 2)
Array.concat(
sort(xs filter (pivot >)),
xs filter (pivot ==),
sort(xs filter (pivot <))
)
}
Scala 不禁止 while,但「Scala 風格」鼓勵以遞迴與高階函數取代可變迴圈。
Scala 的 while 本質可視為庫函數:
def While(p: => Boolean)(s: => Unit) {
if (p) { s; While(p)(s) }
}
呼叫端傳入「傳名參數」(=> Boolean, => Unit),實現類似關鍵字的語法。這展示了「以庫擴展語言」的合成特性——源自 Lisp/Scheme 傳統,也是 DSL 設計的核心思想。
val url = try {
new URL(possibleURL)
} catch {
case ex: MalformedURLException => new URL("www.tedneward.com")
}
進階應用:將橫切關注點(如日誌)封裝為高階函數:
def tryWithLogging(s: => Unit) {
try { s } catch { case ex: Exception => ex.printStackTrace() }
}
// 使用
tryWithLogging { generateException() }
這以一級函數取代 AOP 切面,簡潔且類型安全。
Scala 的 for 實為「for-comprehension」,支援:
i <- 1 to 10(實為 1.to(10) 產生 Range)i % 2 == 0 或 if i % 2 == 0firstName = name.substring(0, name.indexOf(' '))for 多個產生器
// 尋找 .scala 檔案
val filesHere = (new java.io.File(".")).listFiles
for {
file <- filesHere
if file.isFile
if file.getName.endsWith(".scala")
} println("Found " + file)
// grep 範例:雙層迭代
def grep(pattern: String, dir: java.io.File) {
val filesHere = dir.listFiles
for (
file <- filesHere;
if file.getName.endsWith(".scala") || file.getName.endsWith(".java");
line <- scala.io.Source.fromFile(file).getLines;
if line.trim.matches(pattern)
) println(line)
}
大括號語法可省略分號,提升可讀性。for 本質是將集合經過產生、過濾、轉換管線後送入迴圈主體。
match 同為表達式,支援:
case 5 => "five"case s: String => ...case Person(first, last, age) => ...case x if x > 0 => ...case _ => ...
def describe(x: Any) = x match {
case 5 => "five"
case true => "truth"
case "hello" => "hi!"
case Nil => "the empty list"
case _ => "something else"
}
模式匹配廣泛用於解析器、編譯器,也是 case class 的最佳夥伴。
Scala 將控制結構重塑為表達式,並賦予其函數式抽象能力,使語言本身具備擴展性。這不僅改善程式碼表達力,更奠定了 DSL 與內部語言擴展的基礎。