[Dive into Ruby] Ruby 的介绍 主要介绍了 Ruby 的一些特性,[Dive into Ruby] Ruby Basic 变量、常量以及对象 则介绍了关于对象、变量常量的一些知识,这一篇将主要介绍 Ruby 中的程序控制语句,这一部分是每个编程语言的重点,因此会介绍的比较的详细,也会有一些小技巧。
条件控制语句与循环控制语句
条件语句 if\unless and case
首先介绍一下几乎所有高级语言都有的控制语句, if-else
。
在 Ruby 中,if
判断语句跟其它语言没什么区别,如果满足一个条件,则进入一个代码块,否则进入另一个代码块,或者不执行任何操作。写起来也非常的通俗易懂。
需要注意的是,在 Ruby 中,只有false
与nil
这两种情况会导致条件不满足,也就是说,只要值不是false
或者是nil
,if
就是满足的。
if condition then
# block
else
# block
end
if x > 10
# block
end
if "this is a string"
# runs into here
end
if 12
# runs into here
end
if user = User.find_by(id: uid) # 这里涉及到函数的返回值问题,后面会继续讨论
puts user.name
end
if obj.instance_of? Object
# runs into here
end
在这里, then
这个关键字是可以省略的,大多数情况下都没有必要加上,少数特殊情况下不加会导致有歧义,但是也都可以改写。
而如果程序只有if
没有else
的代码块,而且if
的代码块中只有一句话,那么可以缩短成一行实现。
do_sth if condition
如果是否定的语句,可以使用 if not
,也可以使用另一个关键字unless
,很直白的翻译成除非(如果不)
。因此可以这样写。
do_sth unless condition
# 等价于
do_sth if not condition
通常使用 unless
是在只有一个否定的代码块的时候,这个时候使用unless
能够表达比if not
更加清晰的逻辑,并且避免了逻辑非
的运算。在有条件分支的时候,应该使用if-else
的逻辑,避免将unless
与else
搭配(因为这样几乎毫无意义)。
Ruby 中还有一种表示条件的控制语句,叫 case
,用法基本与 Java 中的Switch
相似。
arr = ["string", 19, nil]
arr.each do |item|
case item
when String
puts "It's a string"
when Numeric
puts "It's numeric"
else
puts "It's something not string nor number"
end
end
Notes:
值得注意的是,case-when
中的比较是一种比较广泛的比较,实际上使用的是===
比较,除了比较值之外,还会比较两边是否正则匹配,右边的对象是否属于左边的类等等。因此,在case-when
中是可以直接使用正则表达式的。
循环语句 while\until and more
与if
和unless
的关系类似,while
与until
是一对互为否定的关系。until
=== while not
,使用 unless
与 until
的最主要目的是,使得程序更具有可读性,在看到代码的第一时刻就明白这段代码的条件所在。
while condition do # do 可以省略
end
until condition do # do 可以省略
end
在 Ruby 中,实现循环有多种方式,如 for
循环、loop
循环、while/until
循环、.each
循环、.times
循环等等。在不同的情况下使用不同的循环方式,能够提升程序的可读性。
例如,在需要某段代码执行指定次数的时候,使用 n.times
循环会更加的直接,在需要依次访问数组的元素的时候,使用array.each
,而在需要循环直到某个条件满足或不满足的时候,使用while\until
循环。当然这些循环都是可以在这些场景下使用的,不同的场景使用不同的循环方式,主要是为了程序的可读性以及可理解性。
3.times do
puts "hello"
end
students = ['Andy', 'Bob', 'Cindy']
students.each do |stu|
puts stu # 通过迭代器能够更加简单的使用每一次迭代的元素
end
file = File.new('path')
while line=file.readline
# runs until last line
end
Ruby 中的for
循环在迭代的时候,使用的其实是 .each
方法,因此直接用.each
来迭代就好了。
循环控制语句
在循环中,有时候需要跳出当前循环,或者终止当前循环,那么就需要对应的控制语句来完成。
Ruby 中的循环控制语句有三个 break
、next
还有redo
。redo
用到的非常少,因此暂时不管它。
break
在其它语言中也经常会见到,因此有基础的人也比较容易理解,即当执行到这个语句的时候,终止整个循环程序,进入与循环同一层次的另一段代码。而 next
则没有这么极端,当执行到next
的时候,当前的这次循环将会从这里被跳过,后面的语句不再执行,直接进行下一次循环。
照样来个简单的代码来说明一下。
students = ['Andy', 'Bob', 'Cindy', 'Dave']
students.each do |stu|
if stu == 'Bob'
break
end
puts stu
end
# 程序运行结果:
# Andy
students.each do |stu|
if stu == 'Bob'
next
end
puts stu
end
# 程序运行结果:
# Andy
# Cindy
# Dave
是不是很好理解?
运算符优先级问题
在不使用括号的情况下,各种不同的运算符拥有不同的优先级,简单的例子如,乘除法总是拥有着比加减法更高的优先级,非运算拥有比与、或运算更高的优先级。Ruby 中的运算符非常的多,不同运算符之间的优先级排序表如下。
其中有一些需要特别注意,例如: 按位与(&
)比按位或^
拥有更高的优先级,逻辑与(&&)比逻辑或(||)拥有更高的优先级。
在 Ruby 中,逻辑运算除了与&&
或||
以及非!
三种运算符之外,还有更加可读的 and
or
以及 not
运算符,后面三者在逻辑运算中起着与前面三者相同的作用,但是,注意这个但是,and
or
not
是拥有着更低的优先级的(仅高于控制语句),这意味着在同样的情况下,如果混用 &&
和 not
,是会搞出大事情的。
因此,通常情况下,能够使用逻辑运算符 &&\||\!
的时候,尽量这样使用,一方面它们的优先级较高,可以避免出现很多的问题,另一方面,使用 and\or\not
不太适合加括号,很多时候并没有很方便。
Ruby operators in precedence order. 优先级降序排列
Method | Operator | Description |
---|---|---|
Y | [] []= | Element reference, element set |
Y | ** | Exponentiation |
Y | ! ~ + - | Not, complement, unary plus and minus (method names for the last two are +@ and -@) |
Y | * / % | Multiply, divide, and modulo |
Y | + - | Plus and minus |
Y | >> << | Right and left ⇧ |
Y | & | Bitwise `and' |
Y | ^ | Bitwise exclusive 'or' and regular 'or' |
Y | <= < > >= | Comparison operators |
Y | <=> == === != =~ !~ | Equality and pattern match operators (!= and !~ may not be defined as methods) |
&& | Logical 'and' | |
|| | Logical 'or' | |
.. ... | Range (inclusive and exclusive) | |
? : | Ternary if-then-else | |
= %= { /= -= += | = &= >>= <<= *= &&= | |
defined? | Check if symbol defined | |
not | Logical negation | |
or and | Logical composition | |
if unless while until | Expression modifiers | |
begin/end | Block expression |
关于 Ruby 中的条件以及循环语句就介绍到这里,下一篇会介绍 Ruby 中的方法以及类的概念。