块是括在括号之间的代码块{}(通常用于单行块)或do..end(用于多行块)。
5.times { puts "Hello world" } # recommended style for single line blocks
5.times do
print "Hello "
puts "world"
end # 多行块的推荐样式
5.times {
print "hello "
puts "world" } # 不会引发错误,但是不建议注意:花括号的优先级高于 do..end
可以在单词和方法内部使用块yield:
def block_caller
puts "some code"
yield
puts "other code"
end
block_caller { puts "My own block" } # the block is passed as an argument to the method.
#一些代码
#我自己的街区
#其他代码请注意,如果yield不加阻塞地调用它会引发LocalJumpError。为此,ruby提供了另一种方法,block_given?该方法可让您在调用yield之前检查是否已通过块
def block_caller
puts "some code"
if block_given?
yield
else
puts "default"
end
puts "other code"
end
block_caller
# 一些代码
# 默认
# 其他代码
block_caller { puts "not defaulted"}
# 一些代码
# 没有违约
# 其他代码yield 也可以为块提供参数
def yield_n(n)
p = yield n if block_given?
p || n
end
yield_n(12) {|n| n + 7 }
#=> 19
yield_n(4)
#=> 4尽管这是一个简单的示例,但yield对于允许直接访问另一个对象的上下文中的实例变量或评估而言,这可能非常有用。例如:
class Application def configuration @configuration ||= Configuration.new block_given? ? yield(@configuration) : @configuration end end class Configuration; end app =Application.newapp.configuration do |config| puts config.class.name end # 组态 #=> nil app.configuration #=> #<Configuration:0x2bf1d30>
如您所见,yield以这种方式使用使代码比连续调用更具可读性app.configuration.#method_name。相反,您可以在包含代码的块内执行所有配置。
块的变量是块的局部变量(类似于函数的变量),它们在执行块时消失。
my_variable = 8 3.times do |x| my_variable = x puts my_variable end puts my_variable #=> 0 # 1 # 2 # 8
块无法保存,一旦执行就会死亡。为了保存块,您需要使用procs和lambdas。