Ruby 2.5: How’s That Backtrace looking?

Posted by on December 21, 2017

It’s Christmas night, the air is cool and the stars are unseen through the heavy cloud. Children have left tablet and a nip of whisky out for Santa, and carrots out for the reindeer. One of the children wakes up! Rushing out of bed, she heads to the living room, curious to see if she can catch Santa and reindeer in the act of present delivery.

When she gets there, she finds the food and drink have gone. However there are footprints and reindeer tracks, which lead outside.

As developers, we’re fairly used to following a trail of clues from a point of interest. When a program you’re developing crashes or raises a controlled exception, your tools will typically provide you with as much information as it can about the error. In Ruby, this typically includes a stack trace, showing all the call points on the way to the error. Ruby calls this a “backtrace”.

def turtle_doves
   partridge_in_pear_trees = 1
   partridges(partridge_in_pear_trees)
end

def partridges(number)
  raise “Shouldn’t this be recursive?”
end

turtle_doves

$ ruby test.rb
test.rb:7:in `partridges': Shouldn't this be recursive? (RuntimeError)
    from test.rb:3:in `turtle_doves'
    from test.rb:10:in `<main>'

Something you may not have thought about much is the order in which this stack trace is presented to you. As you can see above, in Ruby 2.4 and earlier you’ll see the error, followed by the location of the code that caused the error, and then site that called that location and so on back to the first line of the program. On a command line, this means that you’ll often see the least useful thing closest to your cursor.

For small stack traces, this is fairly handy! It puts the error information right next to the line that caused the error. For longer stack traces, that you’d typically see in game programming or Rack based web applications, it means you need to scroll off screen to find the error site.

Four years ago, someone suggested a Ruby feature to allow the order of this stack trace to be reversed. This feature will land in Ruby 2.5!

This is backtrace we get from running the same function above under 2.5:

$ ruby test.rb
Traceback (most recent call last):
  2: from test.rb:10:in `<main>'
  1: from test.rb:3:in `turtle_doves'
test.rb:7:in `partridges': Shouldn't this be recursive? (RuntimeError)

This is really handy for those longer stack traces, and is actually how other languages (such as Python) have handled stack traces for a while. However, if you have tooling that parses error output like this (such as a test tool), it will likely be broken by this change. The core team decided to make this a non-optional change for this reason; it means that tooling like this doesn’t have to work out which ordering is being used.

I’m really looking forward to being able to use this; I suspect it will make debugging much easier.

See you tomorrow for one more post about a Ruby 2.5 change!

Ruby 2.5: Not Blocking My Rescue

Posted by on December 20, 2017

Rescuing specific exceptions excessively can cause problems, but if you’ve ever had need to rescue within a do/end block, you might have found yourself using wordy syntax. Ruby 2.5 has a solution for you.

In Ruby 2.5, we’ll get a little syntactic sugar for handling exceptions inside do/end blocks. You can see the feature discussion on Ruby’s Redmine instance. If you’ve ever used the shorthand for rescuing inside a method without using begin/end keywords, this is basically that but inside blocks.

Below we’re going to work through a bit of code, but we’re not going to define all the methods.

Imagine a Santa class, and an algorithm for Santa Claus arriving in town. Santa needs some paper to jot down delivery details. If there is no paper, we raise an error.

class Santa
  def initialize(good, bad)
    @nice_children = good
    @naughty_children = bad
  end

  def make_list
    raise NoPaperError if @paper.nil?
    @list = nice_children.gifts.map(&:details)
  end

  def check_list
    @list.verify_children(nice_children, naughty_children)
  end

   # other Santastic behaviour below
end

We’ll define a global prepare method that takes a block. In Ruby 2.4 when we send the make_list message to Santa within the block, we need to use a full begin/rescue/end clause to describe the behaviour:

def song(children)
  santa = Santa.new(children.good, children.judged_capriciously_by_society)
  prepare do
    # must use `begin` here in Ruby 2.4 and earlier
    begin
      santa.make_list
      2.times { santa.check_list }
    rescue NoPaperError
       santa.request_paper
    ensure
       music_stops
    end
  end
end

def prepare(&block)
  yield
end

If we try to use the shorthand common in Classes, we hit an exception:

def song(children)
  santa = Santa.new(children.good, children.judged_capriciously_by_society)
  prepare do
    santa.make_list
    2.times { santa.check_list }

    rescue NoPaperError
      santa.request_paper
    ensure
      music_stops
    end
  end
end

song(children) #=> SyntaxError:  syntax error, unexpected keyword_rescue, expecting keyword_end

In Ruby 2.5 though, we can do this handily:

def song(children)
  santa = Santa.new(children.good, children.judged_capriciously_by_society)
  prepare do
    # no `begin` keyword!
    santa.make_list
    2.times { santa.check_list }

    rescue NoPaperError
      santa.request_paper
    ensure
      music_stops
    end
  end
end

song(children) # => “music stops”

So that’s nice. See you tomorrow for more Ruby 2.5 news!

Ruby 2.5: yield_self

Posted by on December 19, 2017

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[gift.name] == 0
    @gift_tracker[gift.name] -= 1
    yield
  end
end

gifter = GiftGiver.new(gift)

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

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

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:

(1..10)
  .to_a
  .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| File.open(filename)}.
               yield_self {|file| file.read}.
               yield_self {|contents| YAML.load(contents)}.
               yield_self {|yaml| yaml.fetch[“spec_directory”]}

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

YAML.load(File.open(filename).read).fetch[“spec_directory”]

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!

Ruby 2.5: The Christmas Present

Posted by on December 18, 2017

Let’s talk a wee bit about Ruby 2.5. This starts a week of looking at upcoming features in the language.

Here at FreeAgent Towers, we use a lot of Ruby. The application itself is written in Rails, and our website is static HTML, CSS and JS, but is generated with Middleman. We love it, and so we follow its development closely. One of the exciting points in the Ruby year is the annual release of the next new version of CRuby (formerly MRI). This release has traditionally been around Christmas, and this year is scheduled for Christmas day!

We thought you might be interested in learning about what’s coming down the line, so you know what to look for when you pick up the new version. So over the next few days, we’ll put out a series of small posts, each highlighting one feature from Ruby 2.5.

To get you started, did you know that Ruby 2.5-head is currently around 10% faster than Ruby 2.4.1, and so 165% faster than Ruby 2.0? These are benchmarks so you’ll see different results in production, but those are some impressive improvements.

Until tomorrow!