写ref="/tag/2028/" style="color:#874873;font-weight:bold;">Ruby代码的时候,经常会遇到需要遍历数组或处理一组数据的情况。比如你有一堆待办事项,想一个个打上完成标记。这时候,脚本块和迭代器就能派上用场,不仅让代码更清晰,还能省去一堆重复的逻辑。
什么是脚本块(Block)
Ruby里的块就像一段临时的小任务,可以附在方法后面执行。它用 do...end 或大括号 {} 包起来。比如遍历一个清单:
["收拾书桌", "整理衣柜", "清理浏览器标签"].each do |item|
puts "正在处理:#{item}"
end
这里的 do...end 就是一个块,|item| 是每次拿到的待办项。这种写法比写个 for 循环更直观,也更符合日常语言习惯。
迭代器是怎么工作的
像 each 这样的方法就是迭代器,它知道怎么一步步访问集合里的元素,并把每个元素交给块去处理。你可以把它想象成一个自动传送带,每拿出一个物品,就丢给旁边的工人(也就是块)去操作。
再比如,你想从一堆文件名里挑出以 .log 结尾的日志文件:
files = ["app.rb", "server.log", "readme.md", "debug.log"]
logs = files.select { |f| f.end_with?(".log") }
puts logs.inspect
select 是另一个常用的迭代器,它会根据块里返回的是 true 还是 false 来决定是否保留这个元素。结果就是只留下日志文件,其他都过滤掉。
自己写一个带块的方法
你也可以定义自己的方法来接收块。比如写个“定时提醒”功能,每处理一项就暂停一秒,模拟慢慢整理的过程:
def process_items(items)
items.each do |item|
yield(item)
sleep(1)
end
end
process_items(["备份照片", "删除旧邮件", "归档下载文件夹"]) do |task|
puts "⏰ 开始处理:#{task}"
end
这里的 yield 就是用来执行传入的块。调用时写的那个 do...end 会被原封不动地送到方法内部运行。这种设计让方法变得更灵活,具体做什么由调用者决定。
块和收纳思维的相似之处
其实块的思想和收纳整理很像——都是把重复的动作标准化,然后批量处理。就像你不会每次都重新想一遍怎么叠衣服,而是形成一套流程;在Ruby里,迭代器就是那套“标准动作”,而块就是你针对不同衣物调整的具体手法。
用好块和迭代器,代码看起来不再是一堆指令堆砌,而是像一条清晰的流水线,数据流进去,处理完自动出来,中间过程干净利落。