Ruby Programming/Syntax/Control Structures

維基教科書,自由的教學讀本
跳至導覽 跳至搜尋
上一項: 運算子 索引 下一項: 方法呼叫

條件分支(Conditional Branches)[編輯]

Ruby可藉由條件分支控制程式執行的流程。條件分支依據一個條件式的測試結果為真值偽值,而將流程將轉移至相關連的程式區塊。若條件式計算結果為 falsenil,則視為條件不符 (測試為偽);否則條件成立 (測試為真)。注意,數值 0 視同真值;其他語言多數將 0 視同其偽值。

在許多常見的程式語言中,條件分支是一種敘述,它們決定哪段程式區塊被執行但本身沒有值。 Ruby 則將條件分支作為式子,所以它們也有值。舉例而言,一個 if 式子不只決定執行哪段程式區塊,它本身也會有一個結果值。如下例,該 if 式子之計算結果值為 3:

if true
  3
end

if[編輯]

語法:

 if 條件式 then
   ...程式區塊...
 elsif 其他條件式 then
   ...程式區塊...
 elsif 其他條件式 then
   ...程式區塊...
 else
   ...程式區塊...
 end

範例:

a = 5
if a == 4
  a = 7
end
print a   # prints 5 since the if-block isn't executed

通常我們省略保留字 then 。若想在一行內寫出完整的 if 式,則必須以 then 隔開條件式和程式區塊。如下所示:

if a == 4 then a = 7 end

程序員可藉由 elsifelse 區塊加上更多可用的測試條件以滿足其他需要考慮的情況。僅當執行 if 區塊之條件不符時,才會再考慮 elsifelse 區塊之執行條件。在一個完整的 if 式中,可以有任意數目的 elsif 區塊,但只能有一個 if 和一個 else 區塊。

if修飾片語[編輯]

上述範例亦可改用片語形式表達:

 a = 5
 a = 7 if a == 4

if修飾片語表示當 if 右邊之條件成立時才執行 if 左邊的式子。此一由右到左的演算邏輯並不常見,但它提供了更貼近日常用語的表達形式。由於它不需要 end 結束敘述,所以也具有文字簡潔的優點。 if修飾片語慣例上用於敘述需要加上條件判斷且條件式可以簡短地在一行中寫完的情況。

unless[編輯]

unless式和 if式作用相反,僅當條件不符時才執行相關連的程式區塊。

範例:

 a = 5
 unless a == 4
   a = 7
 end
 print a # prints 7 since the if-block is executed

可將 unless式看作 if式之否定型:

 if !expression     # 此式等於下式
 unless expression

unless修飾片語[編輯]

如同 if修飾片語,unless 也有修飾片語,如下:

 a = 5
 a = 7 unless a == 4
 print a # prints 7 since the if-block is executed

short-if[編輯]

"short-if" 敘述讓我們以很簡短的方式計算式子並回傳一個值。這經常用於串接字串時。

範例:

 a = 5
 plus_or_minus = '+'
 print "The number+1 is: " + (plus_or_minus == '+' ? (a+1).to_s : (a-1).to_s) + "."

"short-if"之語法即 [條件式 ? 式1 : 式2] ,當條件式為真時傳回式1之值,否則傳回式2之值。它也被稱為三元運算子。由於其可讀性較差,建議只使用於次要的工作,如字串格式動作。

 irb> true ? 't' : 'f'
 => "t"
 irb> false ? 't' : 'f'
 => "f"

case[編輯]

我們使用 case 敘述測試一連串的條件。其作用類似 C 和 Java 之中的 switch ,但使用方式更強大。

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

2..5 是表示 範圍(range) 的式子,此例指示在 2 到 5 以內的範圍。如下列算式便可測試 i 的值是否處於 2 到 5 以內之範圍:

(2..5) === i

case 內部使用運算子 === 一次測試多個條件式。基於 Ruby 的個體導向本性,出現在 when 條件中的個體會套用 === 運算,作用如同 (6..10) === i。 在下例中,將會測試字串是否等於第一個 when 中的字串,接著測試是否符合第二個 when字樣規則式

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

迴圈(Loops)[編輯]

while[編輯]

一個 while式就是一個反覆執行的 if式。只要條件成立,程式區塊的內容就會一次又一次地執行。其語法為 while condition ... end ,其中包含當 condition 為真時就重複執行的程式區塊。

語法:

while 條件式 do
  ...程式區塊...
end
while 條件式 :
  ...程式區塊...
end

語法中之 do 或 : 可以省略不寫。但若要在一行內寫出 while 式,則必須以 do 或 : 隔開條件式或程式區塊。

範例:

i = 0
while i < 3 :
    puts i
    i += 1
end

while修飾片語[編輯]

while 也和 ifunless 一樣,有可用於單獨敘述的修飾片語:

irb> i = 0
=> 0
irb> puts i+=1 while i < 3
3
=> nil

下列狀況也可以運作:

 line = inf.readline while line != "what I'm looking for"

當迴圈第一次測試條件式時,區域變數 line 尚未定義,此時其值將被視為 nil 參與條件式測試。

until[編輯]

until式是 while的否定型,當條件式不符時才會反覆執行。

until修飾片語[編輯]

until 也可用修飾片語。

for[編輯]

Ruby 的 for 可提供與 C 的 for 相同的功用,但更有彈性。迴圈可以自行從一個聚合體(colection) - 如陣列、雜湊表、連續數值範圍等等 - 提取一個元素執行,而不需程序員指示它怎麼做:

語法:

for elt in colection do
    # 在此處, elt 參照聚合體中的一個元素。
    ...程式區塊...
end
for elt in colection :
    # 在此處, elt 參照聚合體中的一個元素。
    ...程式區塊...
end

while相同, do 或 : 可省略。

聚合體也可以是一個數值範圍,這用法便是多數人所說的 for 迴圈用法:

irb> for num in (4..6) do
irb>     puts num
irb> end
4
5
6
=> 4..6

此例示範如何從頭到尾一一處理陣列元素:

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

在 Ruby 中, for 其實就是 each迭代器的另一種寫法。下列兩種句型之意義相等:

# C 程序員習慣這種:
for element in collection :
    #... do something
end
# Smalltalk 程序員習慣這種:
collection.each {|element|
    #... do something
}

迭代器通常可以取代傳統的迴圈,一般說來使用迭代器會方便得多。

break[編輯]

break 的意義是脫離迴圈。

next[編輯]

next 的意義是跳到迴圈起始處繼續下一個迭代 (如同 C 的 continue)。

redo[編輯]

redo 將重新開始現行的迭代。

下列以 C 程式碼表現 Ruby 中的 break, next,redo 之作用:

while (condition) {
  label_redo:

    goto label_next;    /* Ruby's "next" */
    continue;

    goto label_break;   /* Ruby's "break" */
    break;

    goto label_redo;    /* Ruby's "redo" */

  label_next:
}
label_break:

return[編輯]

return 不只是脫離迴圈,也會脫離包含這迴圈的方法(method)。如果給它一個引數,該引數將視為方法的回傳值,而不是傳回 nil

於迭代器或程式區塊之中使用 return 時,其意義為脫離包含迭代器或程式區塊的方法,而非僅脫離迭代器或程式區塊。

@@a = [1, 2, 3]

def q1
  @@a.inject(0) {|sum, x|
    x+=1
    return sum + x
  }
end

def q2
  @@a.inject(0) {|sum, x|
    x+=1
    sum + x
  }
end

上例中,return 將直接脫離 q1 方法並回傳sum + x之值,而非僅脫離 inject 區塊。

上一項: 運算子 索引 下一項: 方法呼叫