filmnut
filmnut

Reputation: 746

Why is `yield self` helpful?

As a Ruby newbie, it's confusing to me why it would ever be beneficial to yield self within a method definition. I've come across this functionality in a number of tutorials as being something that is helpful -- it makes perfect sense to me how this works, but I don't understand why you'd ever use it.

Let's say I have the following code:

class Dog

  attr_accessor :breed

  def initialize
    @breed = "Westie"
  end

  def bark
    puts "Woof!"
    yield self if block_given?
  end

end

fido = Dog.new

fido.bark do |d|
  puts "Bark, bark, bark!"
  puts d.breed  
end

So yeah, via yield self, I now have access to the instance of the Dog class within the block that I am yielding too.

But, even if I don't yield self, I would still have access to that instance, right? In other words, wouldn't the code below work exactly the same as the code above?

class Dog

  attr_accessor :breed

  def initialize
    @breed = "Westie"
  end

  def bark
    puts "Woof!"
    yield
  end

end

fido = Dog.new

fido.bark do
  puts "Bark, bark, bark!"
  puts fido.breed   
end

Note that in the second code sample, I'm not calling yield self.

I'm clearly missing the utility here.

Upvotes: 3

Views: 870

Answers (2)

mikej
mikej

Reputation: 66263

The second example works because of the specific circumstances where you have a local variable referring to the the Dog. As an alternative consider what happens if using an anonymous instance:

Dog.new.bark do
  puts "Bark, bark, bark!"
  # what goes here?? puts ????.breed   
end

or maybe you want to declare your block somewhere else and pass it in e.g.

loud = lambda { |dog| puts "A #{dog.breed} doing some LOUD YAPPING" }

puts d.bark(&loud)

so essentially setting up with yield self gives flexibility in how your code can be used.

Upvotes: 5

user229044
user229044

Reputation: 239311

Your examples are pretty simple, and there's no obvious use for yield self in them.

There are cases when it is useful though, the same way that tap is useful: It allows you to define and use a value without introducing a variable in the local scope.

A (admittedly very contrived) example would be:

Dog.new.bark do |d|
  puts d.breed
end

Upvotes: 3

Related Questions