首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Scala 控制結構內幕:if、while、for 與模式匹配的函數式重塑

     編輯:Java 相關知識

Scala 的控制結構雖語法似 Java,但本質全然不同——它們是**表達式**,擁有回傳值,且深度融合函數式特性。本文逐一剖析 if、while、for、try、match 的差異與威力。

if:從語句到表達式

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:不鼓勵但保留的命令式殘留

函數式語言偏好遞迴而非 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 設計的核心思想。

try:同樣是表達式,支援模式匹配捕獲異常


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 切面,簡潔且類型安全。

for:不只是迴圈,是集合處理管線

Scala 的 for 實為「for-comprehension」,支援:

  • 產生器:i <- 1 to 10(實為 1.to(10) 產生 Range)
  • 過濾器:i % 2 == 0 或 if i % 2 == 0
  • 中途賦值:firstName = 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:功能強大的模式匹配

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 與內部語言擴展的基礎。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved