Ruby中的块和产量
我试图理解块和yield
,以及它们如何在Ruby中工作。
如何使用yield
? 我看过的许多Rails应用程序都以一种奇怪的方式使用yield
。
有人可以向我解释或告诉我去哪里了解他们吗?
是的,起初有点令人费解。
在Ruby中,方法可以接收代码块以执行任意代码段。
当一个方法需要一个块时,它通过调用yield
函数来调用它。
例如,这非常方便,可以遍历列表或提供自定义算法。
以下面的例子:
我将定义一个用名称初始化的Person
类,并提供一个do_with_name
方法,该方法在被调用时只传递name
属性到所接收的块。
class Person
def initialize( name )
@name = name
end
def do_with_name
yield( @name )
end
end
这将允许我们调用该方法并传递任意代码块。
例如,要打印我们要做的名字:
person = Person.new("Oscar")
#invoking the method passing a block
person.do_with_name do |name|
puts "Hey, his name is #{name}"
end
将打印:
Hey, his name is Oscar
注意,块接收一个名为name
的变量作为参数(注意,你可以调用这个变量,任何你喜欢的,但是把它name
是有道理的)。 当代码调用yield
它使用@name
的值填充此参数。
yield( @name )
我们可以提供另一个块来执行不同的操作。 例如,反转名称:
#variable to hold the name reversed
reversed_name = ""
#invoke the method passing a different block
person.do_with_name do |name|
reversed_name = name.reverse
end
puts reversed_name
=> "racsO"
我们使用完全相同的方法( do_with_name
) - 它只是一个不同的块。
这个例子很简单。 更有趣的用法是过滤数组中的所有元素:
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"]
我希望这可以帮助你更好地理解它。
顺便说一句,如果该块是可选的,你应该这样称呼它:
yield(value) if block_given?
如果不是可选的,只需调用它。
在Ruby中,方法可以检查它们是否被调用,除了正常参数之外还提供了一个块。 通常这是使用block_given?
完成的block_given?
方法,但您也可以通过在最终参数名称前加一个&符号( &
)来将该块称为明确的Proc。
如果一个方法被一个块调用,那么如果需要的话,该方法可以用一些参数yield
对块的调用(调用块)。 考虑这个示例方法,它演示了:
def foo(x)
puts "OK: called as foo(#{x.inspect})"
yield("A gift from foo!") if block_given?
end
foo(10)
# OK: called as foo(10)
foo(123) {|y| puts "BLOCK: #{y} How nice =)"}
# OK: called as foo(123)
# BLOCK: A gift from foo! How nice =)
或者,使用特殊块参数语法:
def bar(x, &block)
puts "OK: called as bar(#{x.inspect})"
block.call("A gift from bar!") if block
end
bar(10)
# OK: called as bar(10)
bar(123) {|y| puts "BLOCK: #{y} How nice =)"}
# OK: called as bar(123)
# BLOCK: A gift from bar! How nice =)
很有可能有人会在这里提供一个真正详细的答案,但是我总是发现Robert Sosinski的这篇文章是对块,procs和lambda之间细微差别的一个很好的解释。
我应该补充一点,我相信我链接的帖子是针对Ruby 1.8的。 有些事情在ruby 1.9中已经改变了,比如block变量是块本地的。 在1.8中,你会得到如下内容:
>> a = "Hello"
=> "Hello"
>> 1.times { |a| a = "Goodbye" }
=> 1
>> a
=> "Goodbye"
而1.9会给你:
>> a = "Hello"
=> "Hello"
>> 1.times { |a| a = "Goodbye" }
=> 1
>> a
=> "Hello"
我在这台机器上没有1.9,所以上面可能有错误。
链接地址: http://www.djcxy.com/p/4387.html