块是传递给方法的代码段,用 { } 或 do...end 括起来。块是 Ruby 的一个独特、核心特性——它们是将行为传递给方法的方式,支撑了迭代、回调和 Ruby 优雅、富有表现力的风格。
块的语法
[, , ].each { || puts n }
[, , ].each ||
doubled = n *
puts doubled
块被传递给方法(这里是 each),方法会为每个元素调用该块。|n| 声明块的参数(传入的值)。两种语法是等价的;约定俗成使用 { } 表示短块,使用 do...end 表示较长的块。
[1, 2, 3, 4].map { |n| n * 2 } # [2, 4, 6, 8] — transform each
[1, 2, 3, 4].select { |n| n.even? } # [2, 4] — filter
[1, 2, 3, 4].reduce(0) { |sum, n| sum + n } # 10 — accumulate
3.times { |i| puts i } # 0, 1, 2
[1, 2, 3].each_with_index { |val, i| ... }
块是 Ruby 进行迭代和数据转换的方式——你将"要做什么"作为块传递,方法处理迭代。这比显式循环更优雅。
# blocks elegantly handle setup/teardown — the file is auto-closed after the block
File.open("data.txt") do |file|
puts file.read
end # file automatically closed here, even if an error occurs
方法可以使用块来实现设置/清理模式(比如确保文件被关闭)——方法处理资源,在其间调用你的块。
[1, 2, 3].map { |n| n.to_s } # full block
[1, 2, 3].map(&:to_s) # shorthand — &:method calls that method on each element
["a", "b"].map(&:upcase) # ["A", "B"]
&:method 简写是一个简洁的习惯用法,用于只调用每个元素上某一方法的块。
块是 Ruby 最独特和最核心的特性之一——它们是 Ruby 工作原理的基础,也是其优雅、富有表现力风格的基础,因此理解它们对任何 Ruby 开发都是必不可少的。
块是你将行为传递给方法的方式,这推动了 Ruby 的标志性迭代和数据转换方法:与其编写显式循环,不如传递一个描述对每个元素要做什么的块(map、select、reduce、each),方法处理迭代——这样就能得到简洁、可读、函数式风格的代码,这正是 Ruby 的精髓。
块还支持优雅的资源管理模式(方法处理设置/清理,比如自动关闭文件,在其间调用你的块)。
理解块语法({ } 对比 do...end)、块如何接收参数(|n|)、它们如何支持在 Ruby 中频繁出现的 Enumerable 方法,以及像**&:method 简写**这样的习惯用法,是基础的、必须了解的知识——块出现在习惯用法 Ruby 代码的几乎每一行(每个迭代、转换和许多方法调用)。
由于块是 Ruby 设计和表现力风格的核心——支持了其优雅的迭代、回调和资源管理模式——掌握它们对于阅读和编写 Ruby 绝对至关重要,它们是 Ruby 方法的定义性特性,区别于依赖显式循环的语言,使它们成为理解该语言的一个频繁且重要的话题。