跳轉到內容

ooc 程式設計/控制

來自華夏公益教科書
這篇文章是關於計算機程式設計中的控制語句,內容涵蓋虛擬碼Adaooc

條件語句

[編輯原始碼]

條件語句是指只有當特定表示式(即條件)為時才會執行的程式碼塊。

if-else語句是最簡單的條件語句。它們也被稱為分支,因為當程式在執行過程中遇到if語句時,控制權將“分支”到兩個或多個“方向”中的一個。if-else語句通常採用以下形式


if (condition) {
    statement
} else {
    other statement
}

如果原始條件滿足,則第一個語句中的所有程式碼都將被執行。可選的 else 部分指定了一個備用語句,如果條件為假,則執行該語句。具體語法會因程式語言而異,但大多數程式語言(尤其是過程式結構化語言)都內建了某種形式的 if-else 條件語句。if-else 語句通常可以擴充套件為以下形式


if (condition) {
    statement
} else if (condition) {
    other statement
} else if (condition) {
    other statement
...
} else {
    another statement
}

最佳化提示

[編輯原始碼]

當此程式執行時,計算機將按順序檢查所有條件,直到其中一個與它的真值概念相匹配。一旦發生這種情況,程式將執行緊隨其後條件的語句,並繼續執行,而不會檢查任何其他條件。因此,當你試圖最佳化程式時,最好按機率降序排列你的 if-else 條件。這將確保在最常見的場景中,計算機需要做的工作更少,因為它很有可能只需要檢查一兩個“分支”就能找到應該執行的語句。但是,在第一次編寫程式時,不要過多地考慮這一點,以免你進行過早最佳化

話雖如此,你應該知道,最佳化編譯器可能會隨意重新排列你的if 語句,只要該語句沒有副作用。除了其他技術之外,最佳化編譯器甚至可能應用跳轉表二分搜尋


通常需要將一個特定變數與多個常量表達式進行比較。對於這種型別的條件表示式,可以使用match語句。例如

match (x) {
  case 1 =>
     walkTheDog()

  case 5 =>
     launchNuke()
 
  case =>
     selfDestruct()
 }

這裡的最後一個case有一個空的條件。它被稱為catch-all case,如果上面的任何情況都不匹配,則執行該程式碼。

與 C 或 Java 中的switch不同,不需要使用break關鍵字顯式退出一個 case。每個匹配中只執行一個 case。這在犧牲一些靈活性的同時,確保了設計簡單。例如,Duff's device 就不能用 ooc 編寫。

然而,在某些方面,match比 switch 更靈活。例如,你可以有一個沒有初始條件的匹配

match {
  case (x < 0) =>
     -1

  case (x > 0) =>
     1
 
  case =>
     0
}

在這裡,我們在 cases 中定義了自定義條件,而不是要比較的值。圓括號是可選的,但這裡為了可讀性而包含了它們。它的行為與我們在第一行寫了match (true) {完全一樣。

與傳統的switch語句的另一個區別是,match可以用作表示式。在這種情況下,它被評估為執行的 case 中最後一個語句的值。當你將 match 用作表示式時,最好有一個catch-all case,這樣就不會出現值不確定的情況。

最後,值是使用等號運算子==進行比較的,它與任何 ooc 運算子一樣,可以被過載。這意味著match也適用於字串,因為字串在核心 sdk 中過載了==

match (humor) {
  case "sad" =>
     ohNoes()

  case "happy" =>
     yay()
 
  case =>
     bahHumbug()
}

透過過載==運算子,可以在match語句中使用任何使用者定義的型別。

無條件語句

[編輯 | 編輯原始碼]

return 退出當前函式,可以選擇將你給它的任何值傳遞到外部範圍

 return 42

return 不一定總是有一個值,它也可以僅用於在任何時候退出函式

 return

ooc 沒有goto關鍵字。可以使用breakcontinue控制迴圈的流程,並透過return退出函式。ooc 語言力求簡單,並認為goto不屬於高階語言。請參見Edsger Dijkstra的著作以瞭解更多資訊[1]

迴圈允許你重複執行一組語句。

無限迴圈

[編輯原始碼]

無限迴圈是指永不結束的迴圈,其中的語句會無限重複。術語“無限迴圈”是一個相對術語;如果正在執行的程式被某些超出程式控制範圍的手段強行終止,那麼無限迴圈確實會結束。


while (true) {
  doSomething()
}

開頭帶條件的迴圈

[編輯原始碼]

此迴圈在開頭有一個條件。只要條件滿足,這些語句就會重複。如果條件在一開始就不滿足,那麼迴圈內部的語句永遠不會執行。


while (x < 5) {
  x = calculateSomething()
}

中間帶條件的迴圈

[編輯原始碼]

有時你需要先進行計算,並在滿足特定條件時退出迴圈。然而,當條件不滿足時,還需要做其他事情。因此你需要一個迴圈,它的退出條件在中間。


while (true) {
  x = calculateSomething()

  if (x > 5) {
    break
  }

  doSomething(x)
}

跳過迭代

[編輯 | 編輯原始碼]

continue 關鍵字可以用來跳過迴圈體的剩餘部分,並直接進入下一個迭代。

while (true) {
  x = calculateSomething()

  if (x == 5) {
    // skip the 5th step
    continue
  }

  doSomething(x)
}

for 迴圈

[編輯原始碼]

通常情況下,我們需要一個迴圈,其中一個特定的變數從給定的起始值向上或向下計數到特定的結束值。你可以在這裡使用 while 迴圈——但由於這是一個非常常見的迴圈,因此有更簡單的語法可用。


for (i in 1..11) {
   doSomething(i)
}

範圍由 .. 分隔——你可以儲存範圍並在以後重複使用它們,例如:

range := 1..11
// then, later:
for (i in range) {
   doSomething(i)
}

這是可行的,因為 1..11 構造了一個新的 Range,它是一種 覆蓋型別。覆蓋型別將在後面的章節中解釋。

for 允許迭代任何型別的值,只要它們實現了 iterator 方法,並返回一個 Iterator。例如,你可以迭代 ArrayLists

list := ["moody", "jolly", "bored"] as ArrayList<Int>
for (state in list) {
  println(state)
}

華夏公益教科書

[編輯 | 編輯原始碼]

參考文獻

[編輯 | 編輯原始碼]
  1. Edsger Dijkstra (1968 年 3 月). "Go To Statement Considered Harmful" (PDF). Communications of the ACM. 11 (3): 147–148. doi:10.1145/362929.362947. 無節制地使用 goto 語句會導致很難找到有意義的座標來描述程序的進展。 ... goto 語句本身太過原始,它太過容易讓人把程式弄得一團糟。
華夏公益教科書