Ruby Programming/Syntax/Control Structures

上一项: 运算子 索引 下一项: 方法呼叫

条件分支(Conditional Branches)

编辑

Ruby可借由条件分支控制程式执行的流程。条件分支依据一个条件式的测试结果为真值伪值,而将流程将转移至相关连的程式区块。若条件式计算结果为 falsenil,则视为条件不符 (测试为伪);否则条件成立 (测试为真)。注意,数值 0 视同真值;其他语言多数将 0 视同其伪值。

在许多常见的程式语言中,条件分支是一种叙述,它们决定哪段程式区块被执行但本身没有值。 Ruby 则将条件分支作为式子,所以它们也有值。举例而言,一个 if 式子不只决定执行哪段程式区块,它本身也会有一个结果值。如下例,该 if 式子之计算结果值为 3:

if true
  3
end

语法:

 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 叙述测试一连串的条件。其作用类似 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式就是一个反复执行的 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式是 while的否定型,当条件式不符时才会反复执行。

until修饰片语

编辑

until 也可用修饰片语。

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 的意义是脱离回圈。

next 的意义是跳到回圈起始处继续下一个迭代 (如同 C 的 continue)。

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 区块。

上一项: 运算子 索引 下一项: 方法呼叫