Ruby 中的块和产量 [英] Blocks and yields in Ruby
问题描述
我正在尝试了解块和 yield
以及它们在 Ruby 中的工作原理.
I am trying to understand blocks and yield
and how they work in Ruby.
如何使用yield
?我看过的许多 Rails 应用程序都以一种奇怪的方式使用 yield
.
How is yield
used? Many of the Rails applications I've looked at use yield
in a weird way.
有人可以向我解释或告诉我去哪里理解他们吗?
Can someone explain to me or show me where to go to understand them?
推荐答案
是的,一开始有点不解.
Yes, it is a bit puzzling at first.
在 Ruby 中,方法可以接收代码块以执行任意代码段.
In Ruby, methods can receive a code block in order to perform arbitrary segments of code.
当一个方法需要一个块时,您可以通过调用 yield
函数来调用它.
When a method expects a block, you can invoke it by calling the yield
function.
示例:
以 Person
为例,一个具有 name
属性和一个 do_with_name
方法的类.当该方法被调用时,它会将 name
属性传递给块.
Take Person
, a class with a name
attribute and a do_with_name
method. When the method is invoked it will pass the name
attribute to the block.
class Person
def initialize( name )
@name = name
end
def do_with_name # expects a block
yield( @name ) # invoke the block and pass the `@name` attribute
end
end
现在您可以调用此方法并传递任意代码块.
Now you can invoke this method and pass an arbitrary code block.
person = Person.new("Oscar")
# Invoking the method passing a block to print the value
person.do_with_name do |value|
puts "Got: #{value}"
end
会打印:
Got: Oscar
注意该块接收一个名为 value
的变量作为参数.当代码调用 yield
时,它会将 @name
的值作为参数传递.
Notice the block receives as a parameter a variable called value
. When the code invokes yield
it passes as argument the value of @name
.
yield( @name )
可以用不同的块调用相同的方法.
The same method can be invoked with a different block.
例如反转名称:
reversed_name = ""
# Invoke the method passing a different block
person.do_with_name do |value|
reversed_name = value.reverse
end
puts reversed_name
=> "racsO"
其他更有趣的现实生活示例:
Other more interesting real life examples:
过滤数组中的元素:
days = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"]
# Select those which start with 'T'
days.select do | item |
item.match /^T/
end
=> ["Tuesday", "Thursday"]
或按名称长度排序:
days.sort do |x,y|
x.size <=> y.size
end
=> ["Monday", "Friday", "Tuesday", "Thursday", "Wednesday"]
如果块是可选的,您可以使用:
If the block is optional you can use:
yield(value) if block_given?
如果不是可选的,就调用它.
If is not optional, just invoke it.
您可以在您的计算机上使用 irb
(交互式 Ruby Shell)
You can try these examples on your computer with irb
(Interactive Ruby Shell)
以下是复制/粘贴就绪形式的所有示例:
Here are all the examples in a copy/paste ready form:
class Person
def initialize( name )
@name = name
end
def do_with_name # expects a block
yield( @name ) # invoke the block and pass the `@name` attribute
end
end
person = Person.new("Oscar")
# Invoking the method passing a block to print the value
person.do_with_name do |value|
puts "Got: #{value}"
end
reversed_name = ""
# Invoke the method passing a different block
person.do_with_name do |value|
reversed_name = value.reverse
end
puts reversed_name
# Filter elements in an array:
days = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"]
# Select those which start with 'T'
days.select do | item |
item.match /^T/
end
# Sort by name length:
days.sort do |x,y|
x.size <=> y.size
end
这篇关于Ruby 中的块和产量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!