块是一段匿名的代码,通常与方法调用一起使用,类似其他语言中的匿名函数或闭包。块有两种形式:
do ... end
包裹(多行)。{ ... }
包裹(单行)。
块常用于:
each
)。
do ... end
3.times do puts "你好" end
输出:
你好 你好 你好
{ ... }
3.times { puts "你好" }
输出同上。
块可以接受参数,用 |
包裹:
[1, 2, 3].each do |number| puts "数字:#{number}" end
输出:
数字:1 数字:2 数字:3
方法可以通过 yield
调用传入的块,或者显式接收块参数(用 &
)。
yield
def say_hello puts "开始" yield puts "结束" end say_hello do puts "你好,世界!" end
输出:
开始 你好,世界! 结束
yield
def greet(name) yield(name) end greet("张三") do |n| puts "你好,#{n}!" end
输出:
你好,张三!
用 block_given?
判断是否传入了块:
def try_block if block_given? yield else puts "没有传入块" end end try_block { puts "这是一个块" } # 这是一个块 try_block # 没有传入块
方法可以用 &block
显式接收块,并将其作为对象处理。
def run_block(&block) puts "准备执行块" block.call puts "块执行完毕" end run_block { puts "我在块中" }
输出:
准备执行块 我在块中 块执行完毕
def pass_value(&block) block.call("李四") end pass_value { |name| puts "你好,#{name}!" }
输出:
你好,李四!
水果 = ["苹果", "香蕉", "橙子"] 水果.each_with_index do |fruit, index| puts "#{index + 1}. #{fruit}" end
输出:
1. 苹果 2. 香蕉 3. 橙子
学生 = { 姓名: "王五", 年龄: 20 } 学生.each do |键, 值| puts "#{键}:#{值}" end
输出:
姓名:王五 年龄:20
用 map
:
numbers = [1, 2, 3] doubled = numbers.map do |n| n * 2 end puts doubled # [2, 4, 6]
用 select
:
numbers = [1, 2, 3, 4, 5] even = numbers.select { |n| n % 2 == 0 } puts even # [2, 4]
块的最后一行是返回值,常用于方法处理:
def calculate result = yield(5, 3) puts "结果:#{result}" end calculate { |a, b| a + b } # 结果:8 calculate { |a, b| a * b } # 结果:15
块支持中文变量和输出:
任务 = ["写代码", "开会", "休息"] 任务.each do |task| puts "今天要 #{task}" end
输出:
今天要 写代码 今天要 开会 今天要 休息
def timer start = Time.now yield end_time = Time.now puts "耗时:#{end_time - start} 秒" end timer do 5.times { puts "执行中..." } end
输出(示例):
执行中... 执行中... 执行中... 执行中... 执行中... 耗时:0.00234 秒
def repeat(n) n.times { |i| yield(i + 1) } end repeat(3) do |count| puts "第 #{count} 次问候:你好!" end
输出:
第 1 次问候:你好! 第 2 次问候:你好! 第 3 次问候:你好!
class TaskProcessor def process(tasks) tasks.each do |task| yield(task) if block_given? end end end processor = TaskProcessor.new 任务 = ["买菜", "做饭", "吃饭"] processor.process(任务) do |task| puts "正在处理:#{task}" end
输出:
正在处理:买菜 正在处理:做饭 正在处理:吃饭
# Proc my_proc = Proc.new { |x| puts "Proc: #{x}" } my_proc.call(5) # Proc: 5 # Lambda my_lambda = lambda { |x| puts "Lambda: #{x}" } my_lambda.call(10) # Lambda: 10
def run_proc(&block) block.call end proc = Proc.new { puts "你好" } run_proc(&proc) # 你好
x = 0 3.times { x += 1 } puts x # 3
yield
匹配,否则可能报错。
资料来源Ruby 块 – 52kanjuqing-开发者社区,学的不仅是技术,更是梦想