Ruby Blocks and Yield
What is the
yield self if block
does it only mean if there was a block attached to the initiation method it would be called at the end?
def initialize options = {}, &block
@type = self.class.to_s.split('::').last.downcase.to_sym
@version = options.delete(:version) || 1.0
@language = options.delete(:language) || :en
@query = options.delete(:query)
@api_key = options.delete(:key) || :notsupplied
@options = options
raise Error,开发者_如何学Python 'Do not initialize Google::Search; Use a subclass such as Google::Search::Web' if @type == :search
yield self if block
Yep, pretty much. So you can do something like:
Google::Search::Web.new do |search|
# ...
end
(Though, from a software design point of view, running user-specified code in a constructor always seemed strange to me. A better approach is what File
and IO
do, where open
does pretty much the same thing as new
, except that open
runs the passed-in block, whereas new
does not.)
When you write a method like this:
def foo( a, b, &c )
...
end
Then the variable c
is set to a Proc instance if you pass a block to the method, or set to nil
if you don't pass a block. Because nil
is a non-truth value, the method you cite is testing to see if a block was passed to decide whether to yield or not.
As @MarcAndréLafortune says, the better code is: yield if block_given?
. The only times you want to capture a block (that I can think of) are:
- In order to save it into an instance variable for use later:
- e.g.
@foo = c
and then later either invoke it and pass in values (@foo[ 42 ]
), or pass it as a block to another methodmy_array.select(&@foo)
.
- e.g.
- Or, pass it along directly as a block to other methods called by your method:
- e.g.
@my_array = initial_values.select(&c)
- e.g.
精彩评论