Qqwy
Qqwy

Reputation: 5649

Ruby: Yielding from an inner block does not work

I am working on a Ruby project that outputs text where I want to allow other code to change part of the wrapper. Below is a simplified example:

However, I get a very strange error when attempting to run the following code:

def wrapper(&block)
  puts "begin outer wrapper"
  block.call do
    puts "inner content"
  end
  puts "end outer wrapper"
end

wrapper do
  puts "begin inner wrapper"
  yield
  puts "end inner wrapper"
end

I would expect the following output:

begin outer wrapper
begin inner wrapper
inner content
end inner wrapper
end outer wrapper

This does not happen. Instead, Ruby throws the following error: LocalJumpError: no block given (yield)

What is going wrong?

EDIT: Based on @JörgWMittag's answer, this is a variant that does work:

def wrapper(&block)
  puts "begin outer wrapper"
  block.call do
    puts "inner content"
  end
  puts "end outer wrapper"
end

wrapper do |&inner_block|
  puts "begin inner wrapper"
  inner_block.call
  puts "end inner wrapper"
end

Basically, yield and Proc#call() are very different beasts after all.

Upvotes: 2

Views: 242

Answers (1)

Jörg W Mittag
Jörg W Mittag

Reputation: 369633

What is going wrong?

yield transfers control to the block that was passed to the method in whose definition the yield appears. In your case, the yield doesn't appear in a method definition, ergo, there is nowhere to yield to.

Upvotes: 4

Related Questions