Ruby条件判断语句
Ruby条件判断语句
Ruby中条件判断说明
Ruby中支持if、unless、case三种条件判断语句,还支持三目条件运算符expr ? stat1 : stat2
,此外if/unless还可以作为修饰符来简化简单的条件判断语句。
条件判断涉及到true/false的判断,在Ruby中,除了false和nil这两个结果,其它所有值都是true。
另外,Ruby是表达式驱动而非语句驱动的语言,比如if/unless/case都是表达式,在Ruby中它们有返回值:最后执行的那条语句的返回值就是表达式的返回值。
例如:
1 | mark = 90 |
Ruby逻辑运算符
例如:
1 | expression1 or expression2 |
此外,双叹号!!
可将数据按照原true/false值转换成对应的布尔类型。比如:
1 | !!3 #=> true |
if和unless条件判断
if和unless是相反的条件判断,它们语法完全一样。
1 | # 其中then可以省略 |
其中if/unless的then关键字可以在存在换行符或分号的时候省略,例如下面是等价的:
1 | if CONDITION1 |
if和unless作为修饰符
作为修饰符表示if和unless的条件判断语句放在将执行代码的后面。从原来的『如果怎样,就怎样』变成『我要这样,如果是这样的话』。
1 | a=0 |
当有多条语句时,可使用begin…end语句块:
1 | a=0 |
if和unless修饰符后面不能加else类语句。
注意,begin…end没有自己的作用域,它属于语句式代码块。
if中赋值
if是一个语句式的语句块,Ruby中的语句式语句块不会创建新的作用域。
但是有一个比较有趣且某时候很便利的功能,在if中进行赋值会出现什么结果?这分两种情况:(1)在if条件语句中赋值;(2)在if语句体中赋值。
先考察下在if语句体中赋值的有趣现象。
在if语句体中赋值
不管if的判断是否成功,语句体中的赋值语句都会初始化对应的变量。
例如:
1 | if false |
上面的语句,zz=1
这个赋值语句是不执行的,但是zz却已经被初始化了(初始化值为nil),而从未设置过赋值语句的zzz则未初始化。
这是因为局部变量的创建是在编译阶段分配的,在这个阶段它不管赋值语句出现在哪,只要扫描到了就初始化,而且它不管所赋的具体值,仅作初始化动作。等到程序的运行阶段再根据赋值语句做具体的赋值操作。
在if条件语句中赋值
这是个比较智能且有趣的功能。
例如:
1 | if x = 1 |
运行结果:
1 | a.rb:1: warning: found = in conditional, should be == |
它会给个警告,提示用户条件中可能是==
而不是=
,但最终结果仍然是成功的。
因为赋值也是有返回值的,其返回值为所赋的值,即1。所以上面的语句总是返回成功。
如果,赋值一个false或nil,那么将if语句的判断将失败,但是赋值操作却已经完成了:
1 | if z=false |
上面的if语句体中的语句虽然不执行,但是z已经赋值为false,且在if语句之后能使用,因为它不会创建新的作用域。
Ruby对于条件式语句的处理比较智能,如果不是将字面量赋值给变量,就不会出现上面的警告信息。
例如:
1 | z = 1 |
一般来说,对于这种类型的代码,更习惯写成如下形式:
1 | z = 1 |
但有时候在if条件式中赋值也是比较妙的。比如,在if条件式中将正则匹配的结果赋值给变量,如果匹配成功,则变量就被赋值为MatchData对象,语句体就可以执行,如果匹配不成功,则赋值为nil,于是if语句体就不执行。
1 | name = "Gao Xiaofang" |
输出结果:
1 | #<MatchData "ao"> |
当然,这也等价于:
1 | name = "Gao Xiaofang" |
三目运算符
?:
用来简化逻辑简单的if…else…end语句,此外三目运算是一个表达式,它可以直接返回值,于是通过三目运算符来按条件赋值变得非常轻松。
1 | score=59 |
case运算符
case实现分支判断,语句格式为:case … when … then … else … end,else分支是全都when分支都不匹配时将执行的默认分支,then可以省略。
1 | a = 5 |
可以直接将case作为赋值语句的一部分,因为case被执行分支的最后一条语句可以作为返回值。
1 | a = 5 |
上面的示例中,都是case X when EXPR....
格式的,这时是将X的值和EXPR以===
运算符做比较的。而===
是智能比较符号,如果某个类没有重写这个方法(即继承Object的===
),那么它等价于==
,如果重写了,则根据重写规则来判断。通常用于以下几种判断:
- Array和String没有实现
===
,所以这两个类中的===
等价于==
的行为 - 对于Range的行为,所定义的是某对象是否在某个Range范围内
- 对于Module的行为,所定义的是某对象是否是某模块的实例或后裔
- 对于Regexp的行为,所定义的是某对象是否能匹配给定模式,等价于
=~
所以,case语句的功能就更加智能了,例如下面的示例做的是Module测试,测试某对象是否是某模块的实例或子孙。
1 | arr = ["a", 1, nil] |
但是,也可以省略case后的值,直接在when后面写条件表达式,这样就更加灵活:
1 | a = 5 |
多个条件可通过逗号分隔,它们表示or
的关系,当第一个条件为真时,将不会再继续向后匹配:
1 | a = 2 |
a == 1
的时候匹配失败,于是匹配a == 2
,匹配成功,于是退出。