What's new in Ruby 2.3?
Ruby 2.3.0 will be released this Christmas, and the first preview release was made available a few weeks ago. I’ve been playing around with it and looking at what new features have been introduced.
Safe navigation operator
A new operator (&.
) has been introduced.
It can be very useful in cases where you need to check if an object is nil
before calling a method on it.
It will return nil if the object equals nil,
otherwise it calls the method on the object.
There are some caveats to consider.
The first version would evaluate to false if user were set to false,
but the safe navigation operator would throw a NoMethodError
.
This is similar to Rails’
#try!
method.
Frozen string literals
Until Ruby 2.2, strings were mutable by default in Ruby.
We’re allowed to do something like str[2] = 'z'
.
If we want to make strings immutable,
we need to call #freeze
on it (eg. str = 'foobar'.freeze
).
Using frozen (immutable) strings gives us improved performance because Ruby now has to allocate fewer objects. Because of this, there are plans to make strings immutable by default in Ruby 3.0.
To make the transition easier,
Ruby 2.3 allows you to optionally make all strings literals frozen by default.
You can enable this by adding a comment
frozen_string_literal: true
at the start of the file.
When enabled, all the string literals in the file are frozen
even without calling #freeze
on them.
Note that this only enables the feature on files that have the comment.
Although this doesn’t seem like a major change right now, this will pave the way for a smooth transition to Ruby 3.0 a few years from now.
Here’s a detailed post from Alexis Mas explaining immutable strings in Ruby 2.3 if you want to read more about it.
Array#dig
and Hash#dig
This is another useful addition to the standard library. We can now access nested elements in arrays and hashes with a much simpler API.
We can now do this with arrays:
Hashes:
This could be very useful when dealing with JSON data that we’ve parsed into a hash.
“Did you mean?”
When you get a NoMethodError because of a typo in the method name, Ruby now helpfully suggests other method names similar to that one.
This might look like a small change, but it’s my favorite feature in 2.3. Making error messages more helpful has a huge impact on making the language easier to use, especially for beginners.
Hash “comparison”
Hashes now have the comparison methods defined on them.
If you see a >= b
, it is checking
if all the key-value pairs in b are also present in a.
In the first example above,
the key-value pair [:x, 1]
in the RHS is a subset of
those in the LHS - [ [:x, 1], [:y, 2] ]
,
so it returns true.
This also applies to all other comparison operators. Olivier Lacan, who proposed this feature in Ruby, wrote an excellent explanation of hash comparison in Ruby 2.3.
Hash#to_proc
Hash#to_proc
returns a lambda that maps the key with the value.
When you call the lambda with a key,
it returns the corresponding value from the hash.
This might not seem useful in itself.
Why not use []
to access the elements?
But it gets interesting when we use the &
operator to create a proc
and pass it to an Enumerable
block.
Hash#fetch_values
This method works like Hash#values_at
-
it fetches the values corresponding to the list of keys we pass in.
The difference is that #values_at
returns nil when the key doesn’t exist,
while #fetch_values
raises a KeyError
for keys that aren’t present.
Enumerable#grep_v
The grep_v
method is equivalent to
the -v
option in the command line grep utility.
It returns the list of items that do not match the condition.
Numeric#positive?
and #negative?
These functions have been around in Rails core extensions for a while, and now have been included in Ruby.