foo*_*foo 2 ruby yield ruby-block
我对以下几点感到满意:
def some_def(foo, &block)
puts "block utilized below"
block.call(foo)
end
def some_other_def(bar)
puts "using yield below"
yield bar
puts "and back into the method"
end
Run Code Online (Sandbox Code Playgroud)
所以我学会了将块(和过程)与yield关键字分开。
但是,我遇到了以下代码:
# ./open_file.rb
class File
def self.open(name, mode, &block)
file = new(name, mode)
return file unless block_given?
yield(file)
ensure
file.close
end
end
Run Code Online (Sandbox Code Playgroud)
&block当我在 irb 中执行此代码时,参数似乎并不重要:
irb -r ./file.open.rb
Run Code Online (Sandbox Code Playgroud)
并做类似的事情:
File.open('foo.txt','r') {|f| puts f}
Run Code Online (Sandbox Code Playgroud)
通过 in呈现&block为可选block_given?:
return file unless block_given?
Run Code Online (Sandbox Code Playgroud)
&block一般来说,只有在需要将块传递给另一个方法时才使用该参数,例如在这个虚构的示例中:
def m(&block)
some_array.map(&block)
end
Run Code Online (Sandbox Code Playgroud)
Enumerable#sum或者来自 Rails的这个真实版本:
def sum(identity = nil, &block)
if block_given?
map(&block).sum(identity)
else
sum = identity ? inject(identity, :+) : inject(:+)
sum || identity || 0
end
end
Run Code Online (Sandbox Code Playgroud)
无论哪种情况,调用该方法的块都会与另一个方法调用一起使用,因此您需要一种方法来引用该块(即名称)。
所以block_given?/yield和&block服务于不同的目的。能够调用block_given?并不&block多余,并且正如#sum上面的实现一样,它们甚至可以一起使用。