Black Bytes
Share this post!

9 New Features in Ruby 2.4

It has become a tradition to release new Ruby versions on Christmas.

And in this post I want to cover some of the most interesting changes in the next version so you can keep up with the news ๐Ÿ™‚

Float#round with keyword

If you are using floats in your app I hope you use floor or ceil for rounding, because the Float#round method is changing its default behavior in Ruby 2.4.

Example:

The default behavior is now to “round-to-nearest-even”.

UPDATE: The default behavior for Float#round is back to “rounding up” in the final version of Ruby 2.4. This was a decision taken by Matz after this post was originally published.

In addition, Float#round now takes an argument which you can use to define the type of rounding you want.

The options are:

  • :even
  • :up
  • :down

Example:

Also Float#floor, Float#ceil & Float#truncate now take an optional argument that lets you set a precision.

Chomp flag for IO methods

If you ever used a method like gets or each_line I’m sure you remember having to deal with those pesky new line characters.

The ones that looks like this: \n.

This is something beginners always have trouble with, but this new feature might be able to help!

Here’s an example:

Now in Ruby 2.4 you will be able to set the chomp keyword argument & gets will remove the newline character for you.

Example:

This will work with any value that’s not false or nil (the only “falsy” values in Ruby).

So this also works (but not recommended because it can be confusing):

It’s not a super big deal, but it can save you a method call ๐Ÿ™‚

Pathname#empty?

Ruby 2.4 implements Dir#empty? & File#empty?, these methods let you check if a directory or a file is empty (that was pretty obvious, right?).

But Pathname#empty? was also added recently.

In case you are not familiar with Pathname, it’s a class that merges together functionality from both the Dir class & the File class.

In addition, it’s also more “OO” (Object Oriented) in the sense that it returns Pathname objects, instead of strings.

Example:

Commit: https://github.com/ruby/ruby/commit/9373c5efb993dd8cae0526118805449b19af2c22

Set compare_by_identity

Sets are a data structure that is available as part of the standard library. It helps you keep a collection of unique items.

By default the objects are compared based on their value (or to be more accurate, based on their hash value).

But in Ruby 2.4 it’s possible to have a set of unique objects based on their object id.

Example:

If anyone knows of any interesting use for this feature leave a comment ๐Ÿ™‚

Commit: https://github.com/ruby/ruby/commit/76977611dd68e384fdce8c546efda5e1931e67a6

Refinements with Kernel#send, BasicObject#send, Symbol#to_proc

I’m not going to cover refinements in detail here, but the basic idea is to be able to add methods to a class like String, while keeping this change “localized” to one file or class.

Since Ruby 2.4, methods defined via refinements will be available when called via methods like Kernel#send & Symbol#to_proc.

Example:

If you try this in 2.3 or below you will get an ‘undefined method’ error.

Commit: https://github.com/ruby/ruby/commit/35a29390197750abf97ef16fa0740e377764daef

Hash#transform_values

Here’s another method extracted from Rails & coming directly to Ruby. I’m talking about Hash#transform_values, which works in a similar way to Array#map.

Example:

There is also Hash#transform_values! if you need in-place mutation.

Kernel#clone now takes an optional keyword argument

As you may know, it’s possible to make a copy of a Ruby object. This is useful because most Ruby objects are mutable & you may want to avoid making changes to the original object.

We have two methods for making an object copy:

  • clone
  • dup

There are a few small differences between clone & dup, but for this post let’s just say that clone keeps the “frozen” status of the original object while dup does not.

New in 2.4 is the ability to call clone with a “freeze” flag.

Example:

I’m not sure to what extend this is useful, but who doesn’t want more options ๐Ÿ™‚

Commit: https://github.com/ruby/ruby/commit/320ae01c5fb091eab0926c186f304a9caeda1ace

Thread.report_on_exception

Another feature coming with 2.4 is Thread.report_on_exception. This was proposed because Thread exceptions are silent by default, and this can hide problems with your code.

The default value is false, but if your app is using Threads you should try enabling this when upgrading to Ruby 2.4.

Example:

This will show the exception, but it will not crash your program. The alternative is Thread.abort_on_exception, which has always been available.

Notice that there is also an instance version of this method, so you can set this option per-thread instead of all threads.

Binding#irb

Are you a fan of using binding.pry for debugging? Well now we also have binding.irb which works in a similar way.

But since it’s irb you still don’t get all the nice things that pry gives you, like the syntax highlighting.

Better than nothing if for some reason you don’t have access to pry ๐Ÿ™‚

Commit: https://github.com/ruby/ruby/commit/493e48897421d176a8faf0f0820323d79ecdf94a

Conclusion

This new version of Ruby brings in many interesting features, so make sure to check it out when it’s available.

Don’t forget to share this post so more people can learn about these new features in Ruby 2.4!

14 comments
Ivan says 8 months ago

In “Chomp flag for IO methods”

input = gets.chomp

“abc\n”

The chomp would remove the “\n”. It’s probably better to show first the example without the chomp and then with the chomp removing the newline. ๐Ÿ™‚

https://repl.it/Eit4/0

    Jesus Castello says 8 months ago

    Thanks for your comment ๐Ÿ™‚

Paweล‚ Niewiadomski says 8 months ago

You made a mistake with (2.5).round – it will still return 3 in 2.4.0-preview2. I can’t imagine Ruby team deciding to change the default behaviour for such an important method. It would lead to massive amount of bugs.

    Jesus Castello says 8 months ago

    I tried this on 2.4.0-preview3. It also says in the NEWS file that the default behaviour is changing, so I don’t know what to tell you ๐Ÿ™‚

      Paweล‚ Niewiadomski says 8 months ago

      Sorry, didn’t notice there was preview3 already. That’s bonkers!

        Erlingur รžorsteinsson says 8 months ago

        They’re not changing it now, according to Matz: https://bugs.ruby-lang.org/issues/12958#note-18

        Thankfully!

        Jesus Castello says 8 months ago

        Thanks for letting us know. I will add a note to this post ๐Ÿ™‚

Sergey Alekseev says 8 months ago

Wow, โ€œround-to-nearest-evenโ€ sounds really strange to me. What’s the reasoning?

In my view unifying Fixnum and Bignum into Integer is an important thing as well ๐Ÿ™‚

    Jesus Castello says 8 months ago

    Not sure about the reasoning, maybe digging into the feature request could bring some insight into that. And yes the unification is important, but didn’t mention it because other blogs have covered that already ๐Ÿ™‚

    Ben Cullen-Kerney says 8 months ago

    I wasn’t familiar with this rule either, until the calculator app PCalc temporarily removed it a few months ago: http://leancrew.com/all-this/2016/10/well-rounded/.

Curt Sampson says 8 months ago

It avoids “sign bias” that can make some calculations on rounded numbers head significantly away from zero compared to the same calculations on unrounded numbers or rounded versions of numbers that are very close. For example looking at the list [1.5, 2.5, 3.5, 4.5]:

The average of those numbers is 3.
The average of those numbers after rounding each towards even is 3.
If you subtract 0.00001 from each number and then round them away from zero, the average is 3.

However:
* The average of those numbers after rounding each away from zero is 3.5.

    Jesus Castello says 8 months ago

    Thanks for your explanation ๐Ÿ™‚

Philippe Van Eerdenbrugghe says 8 months ago

the reason is to prevent biasing numbers on average upward or downward.

For example if you have a list of numbers that include a lot of x.5 and you were to round all these upward, the average magnitude of the list would also shift upward. Likewise if you round downward, downward.

By rounding to the nearest even number these would balance out, given enough samples.

http://mathematica.stackexchange.com/a/2120/45178

    Jesus Castello says 8 months ago

    Thank you ๐Ÿ™‚

Comments are closed