携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第13天,点击查看活动详情
一、代码块
在 Ruby 中,代码块 BLOCK 本质上可以看做一个匿名的方法。代码块也是对象,是 Proc 类的实例。
匿名代码块有两种创建方法。第一种是使用 {} 包围的方式,将所有的代码放在里面。
{puts "Hello Ruby Block"}
第二种方式是使用 do 和 end 关键字来定义代码块。
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 功能一致。