块是你可以传递给一个 方法的代码片段,这样该方法就可以在它想要的时候运行该代码。
块语法
在 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 的简写语法。