yield 调用传递给方法的代码块 — 它将控制权转移到该代码块,可选地向其传递值,然后恢复方法执行。这是方法调用给它们的代码块的方式,也是 Ruby 迭代和许多优雅模式的机制。
基础 yield — 调用给定的代码块
puts
puts
greet { puts }
当方法调用 yield 时,它运行传递给它的代码块(在 { } 或 do...end 中)。方法控制代码块运行的时间(以及运行多少次)。
def each_pair
yield("a", 1) # pass values to the block's parameters
yield("b", 2)
end
each_pair { |key, value| puts "#{key}: #{value}" }
# Output: a: 1 / b: 2
yield(args) 将值传递给代码块的参数(|key, value|)— 这是迭代方法如何将每个元素提供给代码块的方式。
def my_each(array)
i = 0
while i < array.length
yield(array[i]) # yield each element to the block
i += 1
end
end
my_each([1, 2, 3]) { |n| puts n * 2 } # 2, 4, 6
# this is essentially how Array#each works internally!
这展示了 Ruby 的迭代方法(each、map 等)如何在内部工作 — 它们向代码块 yield 每个元素。
def maybe_yield
if block_given? # check whether a block was passed (avoid an error)
yield
else
"no block"
end
end
# explicitly capture the block as a parameter (with &)
def run(&block) # &block captures the block as a Proc object
block.call # call it explicitly
end
block_given? 检查是否传递了代码块(避免 LocalJumpError),而 &block 将代码块捕获为 Proc 对象,您可以存储或传递它。
理解 yield 是重要的 Ruby 知识 — 它是方法调用代码块的机制,这支撑了 Ruby 的标志性迭代和许多优雅的模式,所以掌握它会阐明 Ruby 的实际工作方式。yield 调用传递给方法的代码块(将控制权转移到它,可选地传递值),这正是 Ruby 的迭代方法(each、map、select)如何在内部运作的 — 它们向代码块 yield 每个元素。
理解这一点揭示了 Ruby 基于代码块的迭代的秘密,并让您编写接受代码块的自己的方法 — 这是创建富有表现力的 API、自定义迭代器、资源管理方法(在代码块周围进行设置/清理)和 DSL 的强大功能。
了解 yield(调用代码块,向其传递参数)、block_given?(安全地检查是否传递了代码块,避免错误)和 &block(显式地将代码块捕获为 Proc)对于理解 Ruby 的迭代和接受代码块的方法如何工作,以及编写您自己的基于代码块的方法都很重要。
由于代码块是 Ruby 的核心,而 yield 是方法使用它们的方式,理解 yield 会加深您对 Ruby 最独特特性(代码块)的理解,并使您能够编写使 Ruby 富有表现力的那种优雅的、接受代码块的方法 — 这是构建清洁 API 的宝贵技能,也是一个常见的面试话题,反映了对 Ruby 代码块机制实际工作原理的理解。