Ruby 2.5: yield_self

yield_self is coming to Ruby 2.5. What is this long requested feature, and how does it work?

Some features take a while to get into a Ruby release. As you can see from the original request on Ruby’s Redmine issue tracker, yield_self has been brewing for 5 years. It has been waiting on a good name, and the Ruby team has settled on one.

But what is it? To understand it, perhaps it is best to look at some existing features. Ruby blocks are one of the ways of passing around functions in Ruby. Every method parameter list has an implicit block argument, which can be used within the method. One of the ways of activating a block is to call yield. For example:

class GiftGiver
  def deliver(gift, &additional_behaviour)
    raise NoGiftError if @gift_tracker[] == 0
    @gift_tracker[] -= 1

gifter =

# Santa Claus
gifter.deliver(new_ruby_version) do |gift|
  puts “Ho ho ho, a holly Merry Christmas. Here’s your #{gift}”

# Ruby core team
gifter.deliver(new_ruby_version) do |gift|
  puts “メリークリスマス!”

The tap method was introduced in Ruby 1.9, and allows you to inspect on and act on a chain of methods. You can see how it’s used in the documentation.

(1..10)                .tap {|x| puts "original: #{x.inspect}"}
  .to_a                .tap {|x| puts "array: #{x.inspect}"}
  .select {|x| x%2==0} .tap {|x| puts "evens: #{x.inspect}"}
  .map {|x| x*x}       .tap {|x| puts "squares: #{x.inspect}"}
“original: 1..10”
“array: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
“evens: [2, 4, 6, 8, 10]
“squares:  [1,4,9,16,25,36,49,64,81,100]”
=> [1,4,9,16,25,36,49,64,81,100]

The advantage of tap is that it always returns the value of the method tap was called on. This means in the above chain, apart from the puts calls, the result is the same as doing:

  .select {|x| x%2==0}
  .map {|x| x*x}
=> [1,4,9,16,25,36,49,64,81,100]

So, where does yield_self come in? It works similarly to tap, but it returns the value of the block you execute each time.

4.tap { |num| num*num } #=> 4
4.yield_self { |num| num*num } #=> 16

This lets you chain together methods that ordinarily wouldn’t be chainable. An example of this is using class methods:

filename.yield_self {|filename|}.
               yield_self {|file|}.
               yield_self {|contents| YAML.load(contents)}.
               yield_self {|yaml| yaml.fetch[“spec_directory”]}

To do this naively without yield_self, you can nest arguments:


So, the trade off here is between a sequence and nesting arguments. There may be some cases where having some sequence methods allows you to be either more expressive or more comprehensible.

You can see a good discussion of this over on Michał Łomnicki’s blog. We’re interested to see where this goes and how frequently it is used!

This entry was filed under Ruby by James. Bookmark the permalink.

About James

James spends his time at FreeAgent reading, writing and occasionally deleting code. He finds joy in helping people, so making the lives of small businesses easier is right up his alley. You can find him frantically amplifying other voices over at @sarcainian.

comments powered by Disqus