Ruby 使用手冊

控制結構 Control structures

本節將探討 Ruby 的控制結構。

case

我們用 case 敘述來測試一連串條件,初看與 C 及 Java 的 switch 相似,但我們之後就會發現 Ruby 的 case 效果更為強大。

ruby> i=8
ruby> case i
    | when 1, 2..5
    |   puts "1..5"
    | when 6..10
    |   puts "6..10"
    | end
6..10
   nil

2..5 是 2 到 5 範圍 (range) 的表示式。以下表示式會測試 i 值是否處於該範圍內:

(2..5) === i

case 內部使用關聯運算子 (relationship operator) ===,同一時間檢查數個條件。為保持 Ruby 的物件導向特質,出現在 when 條件內的物件會以 === 適當解釋。例如,以下程式碼會測試字串是否等於第一個 when 的字串,再測試是否符合第二個 when 的正規表示式。

ruby> case 'abcdef'
    | when 'aaa', 'bbb'
    |   puts "aaa or bbb"
    | when /def/
    |   puts "includes /def/"
    | end
includes /def/
   nil

while

Ruby 能夠以簡單的方式建立迴圈,不過在下一節中,我們會學會使用迭代器 (iterator),那就不再經常需要編寫明顯的迴圈。

while 就是重複的 if, 我們曾在猜字遊戲及正規表示式中使用過(請見前一節);句型為 while condition ... end,所包含的程式碼區塊在條件 (condition) 為真時就會重複。但 whileif 也可以簡單地應用與個別的敘述:

ruby> i = 0
   0
ruby> puts "It's zero." if i==0
It's zero.
   nil
ruby> puts "It's negative." if i<0
   nil
ruby> puts i+=1 while i<3
1
2
3
   nil

你有時候希望否定一個測試條件, unless 就是 if 的否定型,until 則是 while 的否定型。你可以自行試驗看看。

共有四種方式能夠從內部中斷迴圈。第一種是 break,與 C 的一樣,表示完全逸出迴圈; 第二種是 next,跳至迴圈下一個迭代 (iteration) 的起始處(等同於 C 的continue); 第三種是 redo,可重新開始目前的迴圈。以下 C 程式碼用以闡釋 breaknextredo 的意義:

while (condition) {
label_redo:
   goto label_next;        /* ruby's "next" */
   goto label_break;       /* ruby's "break" */
   goto label_redo;        /* ruby's "redo" */
   ...
   ...
label_next:
}
label_break:
...

第四種從內部中斷迴圈的方式是 returnreturn 不單能逸出迴圈,更會逸出包含迴圈的方法。若提供一個參數值,則此方法會回傳這個值,否則會傳回 nil

for

C 程式員現在會好奇怎麼建立一個 "for" 迴圈。Ruby 的 for 具有相同作用,但更有彈性。以下的迴圈會跑一次 集合物件 (collection) 中的每個元素(陣列、雜湊、連續數值等),無需程式員特別指示索引:

for elt in collection
  # ... elt 是集合物件中的一個元素
end

集合物件可以是數值範圍(多數人談及迴圈時,所指的就是這個):

ruby> for num in (4..6)
    |    puts num
    | end
4
5
6
   4..6

本例中,我們會一一說明陣列元素。:

ruby> for elt in [100,-9.6,"pickle"]
    |    puts "#{elt}\t(#{elt.class})"
    | end
100    (Fixnum)
-9.6   (Float)
pickle (String)
   [100, -9.6, "pickle"]

但我們有點超前進度,所以先溫習一下之前所學。for 其實就是 each 的另一種寫法,即是迭代器的第一個範例。以下兩種句型效果相同:

#  如果你習慣用 C 或 Java,你可能會比較喜歡這個。
for element in collection
  ...
end

#  Smalltalk 程式員則可能喜歡這個。
collection.each {|element|
  ...
}

迭代器一般能夠替代傳統的迴圈,熟悉用法後用處會更大。那現在就進入下一節學習吧。

Copyright (c) 2005-2008 Mark Slagell,中文翻譯 Ruby Taiwan 社群

Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.

A copy of the license is included in the section entitled "GNU Free Documentation License."