I understand that
def a(&block)
block.call(self)
end
and
def a()
yield self
end
lead to the same result, if I assume that there is such a block a {}
. My question is - since I stumbled over some code like that, whether it makes any difference or if there is any advantage of having (if I do not use the variable/reference block otherwise):
def a(&block)
yield self
end
This is a concrete case where i do not understand the use of &block
:
def rule(code, name, &block)
@rules = [] if @rules.nil?
@rules << Rule.new(code, name)
yield self
end
yield self enters block, associated with method call, passing current object as argument to the block, plain yield just enters the block without passing any arguments.
The yield keyword, when used inside the body of a method, will allow you to call that method with a block of code and pass the torch, or yield, to that block. Think of the yield keyword as saying: "Stop executing the code in this method, and instead execute the code in this block.
Yield is a keyword (meaning it's a core part of the language) & it's used inside methods for calling a block. Here's what you need to know: Calling a block runs the code inside that block (like calling a method) Yield can pass any number of arguments to the block.
We can explicitly accept a block in a method by adding it as an argument using an ampersand parameter (usually called &block ). Since the block is now explicit, we can use the #call method directly on the resulting object instead of relying on yield .
The only advantage I can think of is for introspection:
def foo; end
def bar(&blk); end
method(:foo).parameters #=> []
method(:bar).parameters #=> [[:block, :blk]]
IDEs and documentation generators could take advantage of this. However, it does not affect Ruby's argument passing. When calling a method, you can pass or omit a block, regardless of whether it is declared or invoked.
The main difference between
def pass_block
yield
end
pass_block { 'hi' } #=> 'hi'
and
def pass_proc(&blk)
blk.call
end
pass_proc { 'hi' } #=> 'hi'
is that, blk
, an instance of Proc
, is an object and therefore can be passed to other methods. By contrast, blocks are not objects and therefore cannot be passed around.
def pass_proc(&blk)
puts "blk.is_a?(Proc)=#{blk.is_a?(Proc)}"
receive_proc(blk)
end
def receive_proc(proc)
proc.call
end
pass_proc { 'ho' }
blk.is_a?(Proc)=true
#=> "ho"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With