跳轉到內容

Scala/表示式,而非語句

來自華夏公益教科書,開放的書籍,開放的世界

簡單的條件分支

[編輯 | 編輯原始碼]

通常,我們需要對變數應該例項化的值做出一個簡單的決定。以一個有點人為的例子為例

var result = ""
if(marks >= 50)
  result = "passed"
else
  result = "failed"
println("Your results just came in, you " + result + ".")

乍一看,它似乎還不錯。但如果分支本身評估了一個值,我們可以做得更好。

println("Your results just came in, you " +
  (if(marks >= 50) "passed" else "failed") + ".")

事實上,Java/C# 為你提供了(...) ? (...) : (...)語法僅僅因為它在某些時候非常方便。

通常,這個結構可以節省 Scala 程式設計師為一個短命的變數發明一個愚蠢的名稱。也許同樣重要的是,它一開始沒有給它分配一個愚蠢的值。

當然,如果該值不止一次被需要,你可能應該引入一個值。即使這樣,

val result: String = if(marks >= 50) "passed" else "failed"
println("Your results just came in, you " + result + ".")
println("Your academic record now shows that you have " + result + " the course.")

這並不阻止你使用if ... else ...作為語句。畢竟,語句是表示式。

擴充套件它

[編輯 | 編輯原始碼]

可以理解的是if ... else if ... else ...鏈同樣常見,它們在 Scala 中也同樣有效。為了獲得更精細的結果,我們可能會嘗試,

val result: String = 
  if(marks >= 85) 
    "A"
  else if(marks >= 70) 
    "B"
  else if(marks >= 60) 
    "C"
  else if(marks >= 50) 
    "D"
  else
    "F"
println("You've got " + result + ".")

但更多時候,我們需要根據值而不是條件進行分支。基本上這就是我們擁有switch在 Java/C# 中。Scala 使用match為此,

val result: String = 
  if(marks >= 85) 
    "A"
  else if(marks >= 70) 
    "B"
  else if(marks >= 60) 
    "C"
  else if(marks >= 50) 
    "D"
  else
    "F"
println("You've got " + result + ".")

result match {
  case "A" | "B" => println("Congratulations!")
  case "C" => println("There is room for improvement, though.")
  case _ => println("We are concerned about your progress.")
}

有幾件事看起來不同。首先,這些案例不使用break來指示分支的結束。你沒有貫穿。不是說你需要貫穿。它們使程式更難閱讀和理解。但是,你可以將等效的案例分組,以便可以處理貫穿的主要用途switch語句。雖然 Scala 沒有default關鍵字,下劃線讀作“其他任何東西”,可以這麼說。

如果你出於某種原因在 Java 1.6 或更低版本中嘗試過,你可能會注意到另一個區別。switch只處理基本型別(以及String從 Java 1.7 開始)因此一個直接的轉換將不得不使用if鏈與幾個equals呼叫。Scala *使用*equals來匹配物件的案例,以使程式碼更易於閱讀。

我們必須在這裡和那裡說更多關於match在這本書中。現在,你可能會欣賞將條件語句和案例混合起來以處理非常特殊情況的能力,例如,

case "D" if marks < 52 => println("Close call!")

儘管為了有意義,這種情況應該位於預設情況之上。

嘗試與失敗

[編輯 | 編輯原始碼]

即使是try ... catch ...塊在 Scala 中也是一個表示式,這會導致非常易讀的程式碼

val n: Int = try {
  userInput.toInt
} catch {
  case _ => 0
}

順便說一下,請注意catch看起來很像match(這裡下劃線表示我們不在乎丟擲了哪個特定的異常)。

華夏公益教科書