Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there any difference in using `yield self` in a method with parameter `&block` and `yield self` in a method without a parameter `&block`?

Tags:

yield

ruby

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
like image 459
Big X Avatar asked Apr 13 '17 11:04

Big X


People also ask

What is self yield?

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.

What is the point of yield in Ruby?

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.

How does yield work in Ruby on Rails?

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.

How do you define a method that can accept a block as an argument?

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 .


2 Answers

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.

like image 141
Stefan Avatar answered Oct 18 '22 05:10

Stefan


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" 
like image 1
Cary Swoveland Avatar answered Oct 18 '22 07:10

Cary Swoveland