块
块(block)就是在调用方法时能与参数一起传递的多个处理的集合。
接收块的方法会执行必要次数的块。块的执行次数由方法本身决定,因此无需事前指定,甚至有可能一次都不执行。
在 Ruby 中,我们常常使用块来实现循环。在接收块的方法中,实现了循环处理的方法称为迭代器(iterator)。each 方法就是一个典型的迭代器。
除了 each 方法,还有 Array#each_with_index 方法,是 [元素, 索引] 两个值被传递到块中。
file_each.rb 读取文件
file = File.open("sample.txt")
file.each_line do |line|
print line
end
file.close
除了逐行循环读取数据的 each_line 方法外,File 对象中还有以字符为单位来循环读取数据的 each_char 方法,以及以字节为单位进行循环读取的 each_byte 方法等。而其他对象也有很多以 each_×× 命名的循环读取数据的方法。
除了迭代器以外,块还被广泛使用在其他地方。其中一个用法就是确保后处理被执行。
file_open.rb
File.open("sample.txt") do |file|
file.each_line do |line|
print line
end
end
<=>联合比较运算符。如果第一个操作数等于第二个操作数则返回 0,如果第一个操作数大于第二个操作数则返回 1,如果第一个操作数小于第二个操作数则返回 -1。
定义带块的方法
total.rb
def total(from, to)
result = 0 # 合计值
from.upto(to) do |num| # 处理从 from 到 to 的值
if block_given? # 如果有块的话
result += yield(num) # 累加经过块处理的值
else # 如果没有块的话
result += num # 直接累加
end
end
return result # 返回方法的结果
end
p total(1, 10) # 从 1 到 10 的和 => 55
p total(1, 10){|num| num ** 2 } # 从 1 到 10 的 2 次幂的和 => 385
total 方法会先使用 Integer#upto 方法把 from 到 to 之间的整数值按照从小到大的顺序取出来,然后交给块处理,最后再将块处理后的值累加到变量 result 中。程序第 5 行中,对 yield 传递参数后,参数值就会作为块变量传递到块中。同时,块的运行结果也会作为 yield 的结果返回。
程序第 4 行的 block_given? 方法被用来判断调用该方法时是否有块被传递给方法,如果有则返回 true ,反之则返回 false。如果方法没有块,则在程序第 7 行中直接把 num 相加。