《Ruby 基础教程》之块

230 阅读2分钟

块(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 相加。