我正在尝试了解 block 和 yield
以及它们在 Ruby 中的工作方式。
如何使用yield
?我看过的许多 Rails 应用程序都以一种奇怪的方式使用 yield
。
有人可以向我解释或告诉我去哪里了解它们吗?
最佳答案
是的,一开始有点费解。
在 Ruby 中,方法可以接收代码块以执行任意代码段。
当一个方法需要一个 block 时,您可以通过调用 yield
函数来调用它。
例子:
以 Person
为例,这是一个具有 name
属性和 do_with_name
方法的类。调用该方法时,它会将 name
属性传递给 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
现在您可以调用此方法并传递任意代码块。
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
请注意,该 block 接收一个名为 value
的变量作为参数。当代码调用 yield
时,它会将 @name
的值作为参数传递。
yield( @name )
可以用不同的 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"
其他更有趣的现实生活例子:
过滤数组中的元素:
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"]
如果该 block 是可选的,您可以使用:
yield(value) if block_given?
如果不是可选的,就调用它。
您可以在计算机上使用 irb
( Interactive Ruby Shell ) 尝试这些示例
以下是复制/粘贴形式的所有示例:
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 - Ruby 中的 block 和产量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3066703/