块是你可以传递给一个 方法的代码片段,这样该方法就可以在它想要的时候运行该代码。
块语法
在 Ruby 中,你可以通过两种方式定义块
- 使用大括号
{} - 使用
do...end
使用大括号
你可以使用大括号 {} 定义块。这最适合单行块。例如,
[1, 2, 3].each { |num| puts num * 2 }
输出
2 4 6
使用 do…end
你可以使用 do...end 定义块。这更适合多行块。例如,
[1, 2, 3].each do |num|
doubled = num * 2
puts doubled
end
输出
2 4 6
块参数
块可以接受放在竖线 | | 中的参数。这些参数在块内充当 变量。例如,
[10, 20, 30].each { |number| puts number + 5 }
输出
15 25 35
在这里,number 是块参数,在迭代过程中代表每个元素。
使用 yield 执行块
方法可以使用 yield 关键字来执行传递给它们的方法。例如,
def greet
puts "Hello!"
yield if block_given?
end
greet { puts "Have a great day!" }
输出
Hello! Have a great day!
该方法调用 yield 来运行块。block_given? 检查确保存在一个块,以避免错误。
注意:如果你在没有块的情况下使用 yield,Ruby 将会抛出名为 LocalJumpError 的错误。这就是为什么我们在调用 yield 之前使用 block_given? 进行检查。
你还可以通过在方法参数中添加 &block 将块捕获为 Proc 对象,从而允许你显式调用块。例如,
def greet(name, &block)
puts "Hello, #{name}"
block.call if block
end
greet("Alice") { puts "Welcome!" }
输出
Hello, Alice Welcome!
BEGIN 和 END 块
Ruby 允许你在程序开始前和结束后运行一些代码,方法是使用 BEGIN 和 END 块。
BEGIN在程序开始时运行。END在程序执行完成后立即运行。
示例
BEGIN {
puts "Start of the program."
}
END {
puts "End of the program."
}
puts "This is the main program."
输出
Start of the program. This is the main program. End of the program.
注意:BEGIN 和 END 块很少使用,通常保留给特殊用途。
常用使用块的方法
Ruby 提供了许多内置方法,这些方法接受块来进行迭代、转换和过滤。
| 方法 | 描述 | 示例 |
|---|---|---|
.each |
遍历集合中的每个元素。 | [1, 2, 3].each { |n| puts n } |
.map |
转换每个元素并返回一个新数组。 | [1, 2, 3].map { |n| n * 2 } |
.select |
返回块返回 true 的元素。 |
[1, 2, 3, 4].select { |n| n.even? } |
.times |
指定次数执行一个块。 | 3.times { puts "Hi" } |
更多关于 Ruby 块
你可以将参数和块都传递给方法。例如,
def repeat(count)
count.times { yield if block_given? }
end
repeat(3) { puts "Hi!" }
输出
Hi! Hi! Hi!
Proc(“过程”的缩写)允许你将一段代码保存到变量中,并在以后使用它。例如,
message = Proc.new { puts "Welcome to Ruby!" }
message.call
# Output: Welcome to Ruby!
在这里,我们将一个块存储在 message 变量中,并通过 .call 来运行它。
你也可以将 proc 传递给方法
def run_twice(block)
block.call
block.call
end
greeting = Proc.new { puts "Hello World!" }
run_twice(greeting)
输出
Hello World! Hello World!
在这里,我们将 greeting proc 传递给了 run_twice 方法,该方法会调用它两次。
lambda 类似于 proc,但它更严格一些。它会检查参数数量,并且在 return 语句方面的行为有所不同。例如,
goodbye = -> { puts "Hello World!" }
goodbye.call
# Output: Hello World!
在这里,-> 是 lambda 的简写语法。