[Ruby] 表达式

1. 运算符表达式

Ruby提供了基本的运算符集,也提供了几个独特的运算符。Ruby中的许多运算符是由方法调用来实现的。例如,当执行"a*b+c"时,实际上是请求a对象执行方法*,传入的参数是b。因为任何东西都是对象,而且可以重新定义实例方法,所以可以重新定义任何基本算术方法,例如:

class Fixnum
  def +(other)
    old_plus(other).succ
  end
end

如果用反引号"`",或者以"%x"为前缀的分界形式,括起一个字符串,默认情况下它会被当作底层操作系统的命令来执行。表达式的返回值就是该命令的标准输出,例如:

`date`


2. 赋值

赋值语句将左侧的变量或者属性设置为右侧的值,然后返回该值作为赋值表达式的结果。这意味着可以链接赋值语句,例如:

a = b = 1

定义一个可写的对象属性,只需简单地定义一个以等于号结尾的方法即可,例如:

class Test
  def value=(new_value)
    @value = new_value
  end
end

Ruby的赋值是以并行方式执行的,所以赋值语句右边的值不受赋值语句本身的影响。在Ruby中可以用并行赋值来交换两个变量的值,例如:

a, b = b, a

当赋值语句有多于一个左值时,赋值表达式将返回由右值组成的数组。如果赋值语句的左值多于右值,那么多余的左值将被忽略。如果右值多于左值,那么额外的右值将被忽略。如果赋值语句仅有一个左值而有多个右值,那么右值将被转换成数组,然后赋值给左值。

如果最后一个左值有一个"*"前缀,那么所有多余的右值将被集合在一起,并作为一个数组赋给左值。同样,如果最后一个右值是一个数组,可以在它的前面加一个"*",它将被适当地展开成其元素的值,例如:

a, *b = [1, 2, 3]
a, b = *[1, 2]

赋值语句的左边可以含有一个由括号括起来的变量列表,Ruby视这些变量为嵌套赋值语句,在处理更高层次的赋值语句前,Ruby会提取出对应的右值,并赋值给括起来的变量,例如:

a, b, c, d = 1, [2, 3], 4
a, [b, *c], d = 1, [2, 3, 4], 5

Ruby有一个句法的快捷方式,如"a = a + 2"可以写成"a += 2",内部处理时,会将第二种形式先转换成第一种形式。


3. 布尔表达式

Ruby对真值的定义是:任何不是nil或者常量false的值都为真。Ruby支持所有的标准布尔操作符,并引入了一个新操作符defined?。仅当"and"和"&&"的两个操作数都为真时结果才为真,并且仅当第一个操作数为真时才求解第二个操作数的值。同样,如果有一个操作数为真,那么"or"和"||"的结果为真,且权当第一个操作数为假时才求解第二个操作数。"not"和"!"返回它们的操作数的相反值。

如果参数未被定义,defined?操作符返回nil,否则返回对参数的一个描述,如果参数是yield,而且有一个block和当前上下文相关联,那么defined?返回字符串yield。

Ruby对象还支持如下比较方法:==,===,<=>,=~,eql?和equal?。除了"<=>",其他方法都是在类Object中定义的,但是经常被子类重载以提供适当的语义。比如类Array重定义了"==",当两个数组对象有相同的元素个数,且对应的元素个数也都相等时,才认为它们相等。

常用的比较操作符
操作符
含义
==测试值相等与否。
===用来比较case语句的目标和每个when从句的项。
<=>通用比较操作符。
<, <=, >=, >小于、小等于、大等于、大于比较操作符。
=~正则表达式模式匹配操作符。
eql?如果接受者和参数有相同的类型和相等的值,则返回真。
equal?如果接受者和参数有相同的对象ID,则返回真。

"=="和"=~"都有相反的形式:"!="和"!~",不过,在Ruby读取程序的时候,会对它们进行转换。

Ruby的if表达式和其他语言的if语句类似,例如:

if condition then
  statement
elsif condition then
  statement
else
  statement
end

如果将if语句分布到多行上,那么可以不用then关键字。使用冒号来替代then可以使代码更简洁,例如:

if condition : statment
elsif condition : statment
else statement
end

Ruby还有一个否定形式的if语句unless,例如:

unless condition
  statement
else
  statement
end

Ruby也支持C风格的条件表达式,例如:

new_value = condition ? true_value : false_value


4. Case表达式

Ruby的case表达式相当于多路的if,而它有两种形式。

第一种形式接近于一组连接的if语句,它列出一组条件,并执行第一个为真的条件表达式所对应的语句,例如:

case
when condition1 : statement1
when condition2 : statement2
else statement3
end

第二种形式是在case语句的顶部指定一个目标,而每个when从句列出一个或者多个比较条件,例如:

case match
when value1
  statement1
when value2
  statement2
when value3
  exit
else
  statement3
end

和if一样,case返回执行的最后一个表达式的值,而且如果表达式和条件在同一行上的话,可以用then关键字来加以区分。

case通过比较目标和when关键字后面的比较表达式来运作,这个测试通过使用"==="来完成。只要一个类为"==="提供了有意义的语义,那么该类的对象就可以在case表达式中使用。Ruby的所有类都是类Class的实例,它定义了"==="以测试参数是否为该类或其父类的一个实例,所以case可以用来测试对象到底属于哪个类。


5. 循环

只要条件为真,while循环就会执行循环体,例如:

while line = gets
end

until循环与此相反,它执行循环体直到循环条件变为真,例如:

until value > 10
  value += 1
end

使用while和until做语句修饰符时,如果被修饰的语句是一个begin/end块,那么不管布尔表达式的值是什么,块内的代码至少会执行一次,例如:

puts 'Hello' while false #nothing
begin
  puts 'World'
end while false #World

for在Ruby中是一个语法块,当使用for时,Ruby将把它转换成each迭代器,例如:

for i in [1, 2, 3, 4]
  puts i
end

循环控制结构break、redo和next可以改变循环或者迭代的正常流程,break终止最接近的封闭循环体,然后继续执行block后面的语句,redo从循环头重新执行循环,但不重计算循环条件表达式或获得迭代中的下一个元素,next跳到本次循环的末尾,并开始下一次迭代,例如:

while line = gets
  next if line =~ /^[a-z]+/
  break if line =~ /^END/
  redo if line =~ /^[0-9]+/
end

在Ruby 1.8中,可以传递一个值给break和next,比如可以对break设置循环的返回值。

redo语句使得一个循环重新执行当前的迭代,但是retry可以从头重新执行一个循环,例如:

for i in 1..100
  retry if gets =~ /^RETRY/
end


6. 作用域

while,until和for循环没有引入新的作用域,已存在的局部变量可以在循环中使用,而循环中新创建的局部变量也可以在循环后使用。

被迭代器使用的block略有不同,这些block中创建的局部变量通常无法在block外访问。如果执行block的时候,一个局部变量已经存在且与block中的变量同名,那么block将使用此已有的局部变量,例如:

x = 1
y = 2
[1, 2, 3].eachdo |x|
  y = x + 1
end
puts x #x=1
puts y #y=4

在外部作用域中变量不必有值,Ruby解释器只需看到它即可,例如:

if false
  a = 1
end
3.times {|i| a = i}
puts a #a=2



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值