Ruby 手册 | 13 - Ruby 代码块

116 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第13天,点击查看活动详情

一、代码块

在 Ruby 中,代码块 BLOCK 本质上可以看做一个匿名的方法。代码块也是对象,是 Proc 类的实例。

匿名代码块有两种创建方法。第一种是使用 {} 包围的方式,将所有的代码放在里面。

{puts "Hello Ruby Block"}

第二种方式是使用 doend 关键字来定义代码块。

do 
    puts "This is Block"
end

一旦代码块被创建,就可以将它与方法的调用相关联,在方法中使用 yield 方法就可以回调改代码块。

def run_twice
  puts "Start"
  yield
  yield
  puts "Stop"
end

run_twice {puts "Say Hi Block"}

i = 0
run_twice do
  i += 1
  puts i
end

puts i

执行上述代码,输出结果如下:

Start
Say Hi Block
Say Hi Block
Stop
Start
1
2
Stop
2

语句 run_twice {puts "Say Hi Block"} 将代码块 {puts "Say Hi Block"} 关联至 run_twice 方法,在 run_twice 方法中执行了两次。后面的代码 i += 1 也执行了两次,不过值得注意的是代码块维持了调用前的上下文,能够对变量 i 进行累加。

代码块也能够接收参数,在定义代码块之前需要用到竖线 || ,包含对变量的定义,如

{|x| puts x}
do |x, y|
    puts x + y
end

在回调代码块的时候,直接使用 yield 加上传入的参数,例如:

yield 1
yield (1, 2)

再看传递参数的运行两次的代码,代码如下:

def run_twice(arg)

  puts "Start"
  yield arg
  yield arg
  puts "End"
end

run_twice("hello") {|word| puts word}

i = 0
run_twice(2) do |x|
  i += x
  puts i
end

puts i

执行上述代码,输出结果如下:

Start
hello
hello
End
Start
2
4
End
4

上述代码中使用参数可以自己指定需要重复两次输出的文字,也可以指定两次累加的步长,run_twice 方法始终专注的是重复两次执行的该你那,完全不关系到底需要在执行什么逻辑的代码,这样的设计往往有助于程序更好的实现功能上的分割,并使得高效的重复使用代码成为可能。

二、yield 和迭代

Ruby 库中大量使用代码块来实现迭代,在之前的代码中使用过的数组和区间的 each 方法就是代码块。

class Array
  def for_each
    # 遍历数组
    for i in (0..self.length - 1)
      yield self[i]
    end
  end
end

(["a", "1", "c"]).for_each{|i| puts i}

sum = 0
[1, 2, 3, 4, 5].for_each do |i|
  sum += i
end

puts sum

执行上述代码,输出结果如下:

a
1
c
15

上述代码中使用 yield 为 Array 对象实现了一个 for_each 功能,与 each 功能一致。