Control Expressions
Ruby 有多种方式来控制执行。这里描述的所有表达式都返回一个值。
对于这些控制表达式中的测试,nil并且false是假值true和任何其他对象都是真值。在这个文件中,“真”意味着“真值”和“假”意味着“假值”。
if 表达
最简单的if表达式有两个部分,一个是 “test” 表达式和一个 “then” 表达式。如果“测试”表达式评估为真,则评估“那么”表达式。
这是一个简单的 if 语句:
if true then
puts "the test resulted in a true-value"
end这将打印出“测试结果为真实值”。
then是可选的:
if true
puts "the test resulted in a true-value"
end本文档将省略then所有表达式的可选项,因为这是最常见的用法if。
你也可以添加一个else表达式。如果测试未评估为真,则else表达式将被执行:
if false
puts "the test resulted in a true-value"
else
puts "the test resulted in a false-value"
end这将打印出“测试结果为假值”。
您可以使用添加任意数量的额外测试到 if 表达式elsif。一个elsif当上述所有测试执行elsif都是假的。
a = 1
if a == 0
puts "a is zero"
elsif a == 1
puts "a is one"
else
puts "a is some other value"
end这将打印“一个是” 1不等于0。由于else仅在没有匹配条件时执行。
一旦条件匹配,if条件或任何elsif条件,if表达式就完成了,不再执行进一步的测试。
像一个if,一个elsif条件可能会跟着一个then。
在这个例子中只有“a is one”被打印出来:
a = 1
if a == 0
puts "a is zero"
elsif a == 1
puts "a is one"
elsif a >= 1
puts "a is greater than or equal to one"
else
puts "a is some other value"
end测试if和elsif可能有副作用。副作用最常见的用途是将值缓存到局部变量中:
if a = object.some_value
# do something to a
endif表达式的结果值是表达式中执行的最后一个值。
Ternary if
你也可以使用?和写一个 if-then-else 表达式:。这三元如果:
input_type = gets =~ /hello/i ? "greeting" : "other"与此if表达式相同:
input_type =
if gets =~ /hello/i
"greeting"
else
"other"
end虽然三元 if 比写得比较冗长的形式要短得多,但为了便于阅读,建议三元if仅用于简单条件。此外,避免在同一表达式中使用多个三元条件,因为这可能会造成混淆。
unless 表达
unless表达式是相反if的表达。如果该值为 false,则执行 “then” 表达式:
unless true
puts "the value is a false-value"
end这不会打印任何内容,因为 true 不是假值。
您可以使用一个可选的then带unless一样if。
请注意,上述unless表达式与以下内容相同:
if not true
puts "the value is a false-value"
end就像if表达式一样,您可以使用以下else条件unless:
unless true
puts "the value is false"
else
puts "the value is true"
end这从else条件打印出“值为真” 。
您不得使用elsif与unless表达。
unless表达式的结果值是表达式中执行的最后一个值。
修饰符if和unless
if并且unless也可以被用于修改的表达式。当用作修饰符时,左边是 “then” 表达式,右边是 “test” 表达式:
a = 0
a += 1 if a.zero?
p a这将打印1。
a = 0
a += 1 unless a.zero?
p a这将打印0。
虽然修饰符和标准版本同时具有“测试”表达式和“然后”表达式,但由于解析顺序,它们并不是彼此的精确转换。以下是一个显示不同之处的例子:
p a if a = 0.zero?这引发了 NameError“ 未定义的局部变量或方法`a'”。
当 ruby 分析这个表达式时,它首先会a在 “then” 表达式中遇到一个方法调用,然后它会a在 “test” 表达式中看到该赋值并将其标记a为局部变量。
当运行这条线时,它首先执行“测试”表达式a = 0.zero?。
由于测试是真的,它执行“then”表达式,p a。由于a在体内被记录为不存在的方法,所以引发了 NameError。
同样如此unless。
case 表达
case表达式可以以两种方式使用。
最常见的方法是将对象与多种模式进行比较。这些模式使用+ === +方法进行匹配,该方法在 Object 上使用别名+ == +。其他类必须覆盖它以提供有意义的行为。有关示例,请参阅模块#===和正则表达式#===。
下面是一个case用来比较 String 和模式的例子:
case "12345"
when /^1/
puts "the string starts with one"
else
puts "I don't know what the string starts with"
end这里通过调用返回值"12345"来比较字符串。与表达式一样,匹配的第一个匹配被执行,所有其他匹配都被忽略。/^1//^1/ === "12345"trueifwhen
如果找不到匹配项,else则执行。
else和then是可选的,case表达产生相同的结果与上述一个:
case "12345"
when /^1/
puts "the string starts with one"
end你可以在同一个地方放置多个条件when:
case "2"
when /^1/, "2"
puts "the string starts with one or is '2'"
endRuby 会依次尝试每个条件,所以首先/^1/ === "2"返回false,然后"2" === "2"返回true,所以打印出“字符串以1开头或者是'2'”。
你可以then在when条件后使用。这是最经常用来放置when在一条线上的主体。
case a
when 1, 2 then puts "a is one or two
when 3 then puts "a is three"
else puts "I don't know what a is"
end使用case表达式的另一种方式就像是一个 if-elsif 表达式:
a = 2
case
when a == 1, a == 2
puts "a is one or two"
when a == 3
puts "a is three"
else
puts "I don't know what a is"
end再次,then和else是可选的。
case表达式的结果值是表达式中执行的最后一个值。
while 循环
while循环执行,而条件为真:
a = 0
while a < 10 do
p a
a += 1
end
p a打印数字0到10. a < 10在进入循环之前检查条件,然后执行主体,然后再次检查条件。当条件结果为 false 时,循环终止。
do关键字是可选的。以下循环等同于上面的循环:
while a < 10
p a
a += 1
endwhile循环的结果是nil除非break用于提供值。
until 循环
until循环执行,而条件是假的:
a = 0
until a > 10 do
p a
a += 1
end
p a这会打印数字0到11.与 while 循环一样a > 10,进入循环时每次执行循环体时都会检查条件。如果条件为假,循环将继续执行。
像while循环一样,do是可选的。
像while循环一样,循环的结果until是零,除非break被使用。
for 循环
该for循环由for一个变量组成,后面跟着一个变量以包含迭代参数,后面跟着in使用每个参数迭代的值。do是可选的:
for value in [1, 2, 3] do
puts value
end打印1,2和3。
喜欢while和until,这do是可选的。
for循环类似于使用每一个,但不创建一个新的变量范围。
除非break使用for循环的结果值是迭代的值。
for循环在现代 Ruby 程序很少使用。
修饰符while和until
像if和unless,while并且until可以用作改性剂:
a = 0
a += 1 while a < 10
p a # prints 10until 用作修饰词:
a = 0
a += 1 until a > 10
p a # prints 11您可以使用begin和end创建一个while循环,在条件之前运行一次该主体:
a = 0
begin
a += 1
end while a < 10
p a # prints 10如果你不使用rescue或者ensure,Ruby 优化任何异常处理开销。
break Statement
使用break可以尽早离开。values如果其中一个是偶数,这将停止迭代项目:
values.each do |value|
break if value.even?
# ...
end您也可以while使用break以下命令终止循环:
a = 0
while true do
p a
a += 1
break if a < 10
end
p a这将打印数字0和1。
break 接受一个值,该值提供表达式结果“破坏”的结果:
result = [1, 2, 3].each do |value|
break value * 2 if value.even?
end
p result # prints 4next Statement
使用next跳过当前迭代的其余部分:
result = [1, 2, 3].map do |value|
next if value.even?
value * 2
end
p result # prints [2, nil, 6]next 接受可用作当前块迭代结果的参数:
result = [1, 2, 3].map do |value|
next value if value.even?
value * 2
end
p result # prints [2, 2, 6]redo Statement
使用redo重做当前迭代:
result = []
while result.length < 10 do
result << result.length
redo if result.last.even?
result << result.length + 1
end
p result这会打印 0,1,3,3,5,5,7,7,9,9,11
在Ruby 1.8中,你也可以使用retry你使用的地方redo。这不再是真实的,现在当您retry在rescue块外部使用时,您将收到 SyntaxError 。请参阅例外以正确使用retry。
Flip-Flop
触发器是一个罕见的条件表达式。它的主要用途是用于从使用 ruby 一个行程序处理的文本ruby -n或ruby -p。
触发器的形式是表示何时触发器打开的表达式,..(或...)表示何时触发器将关闭的表达式。当触发器处于打开状态时,它将继续评估true和false关闭。
这里是一个例子:
selected = []
0.upto 10 do |value|
selected << value if value==2..value==8
end
p selected # prints [2, 3, 4, 5, 6, 7, 8]在上面的例子中,开启条件是n==2。触发器最初关闭(假)为0和1,但在2时开启(真),并保持在8上.8关闭后,关闭9和10。
触发器必须条件这样的里面被用作if,while,unless,until等,包括改性剂的形式。
当您使用包含范围(..)时,关闭条件在条件更改时进行评估:
selected = []
0.upto 5 do |value|
selected << value if value==2..value==2
end
p selected # prints [2]在这里,触发器的两端都被评估,所以触发器只有在value等于2 时才会打开和关闭。由于触发器在迭代中打开,它将返回 true。
当您使用独占范围(...)时,关闭条件将在以下迭代中进行评估:
selected = []
0.upto 5 do |value|
selected << value if value==2...value==2
end
p selected # prints [2, 3, 4, 5]这里,触发器在value等于2 时打开,但在同一次迭代中不关闭。关闭条件不会被评估,直到接下来的迭代,并且value永远不会再是两次。
本文档系腾讯云开发者社区成员共同维护,如有问题请联系 cloudcommunity@tencent.com

