Skip to content
← All posts
4 min read Dawid Skłodowski

Ruby 2.4: unified Integer and faster hashes

Ruby 2.4.0 arrives on Christmas Day with a long-overdue cleanup — Fixnum and Bignum merged into one Integer — plus a faster Hash, Enumerable#sum, Regexp#match?, and binding.irb. A practical tour.

Ruby 2.4.0 has arrived on schedule for Christmas, and it is a release with a satisfying mix of long-overdue cleanup and quiet performance work. The headline is a simplification you will appreciate conceptually even if it changes little in your code, and underneath it are real speedups and a handful of genuinely useful new methods. Here is the tour.

Fixnum and Bignum become Integer

For its whole history Ruby has had two integer classes: Fixnum for small integers that fit in a machine word, and Bignum for larger ones, with Ruby transparently promoting between them. You rarely noticed — 2 + 2 and 10**100 both just worked — but the split was a leaky abstraction that occasionally surfaced in confusing ways (a value’s class changing as it grew, is_a?(Fixnum) checks that broke on big numbers). 2.4 unifies them into a single Integer class:

1.class           # => Integer   (was Fixnum)
(10**100).class   # => Integer   (was Bignum)

The behaviour is identical — Ruby still uses an efficient representation internally for small numbers — but the conceptual model is now clean: an integer is an Integer, full stop. Fixnum and Bignum remain as deprecated aliases so old code does not break, but the right mental model and the right thing to reference is now just Integer. It is the kind of cleanup that makes the language easier to teach and to reason about, removing a distinction that never should have been visible to users.

Faster hashes

Hashes are everywhere in Ruby — options, JSON, every keyword argument, the internals of the language itself — so making them faster is a broad win. Ruby 2.4 reworks the Hash implementation to use open addressing, a more cache-friendly internal structure that improves lookup and insertion performance, especially for the small-to-medium hashes that dominate real code. You change nothing and your hash-heavy code gets faster, which on a typical Rails request — built on a mountain of hashes — is a free, broad improvement of exactly the kind that makes upgrading worthwhile.

Enumerable#sum: at last

A small addition that removes a tiny daily friction. Summing a collection used to mean inject(:+) or reduce(0, :+) — fine, but slightly cryptic and slower than it needed to be. 2.4 adds a proper Enumerable#sum:

[1, 2, 3, 4].sum            # => 10
items.sum(&:price)          # => total price
[1.0, 2.0].sum(100)         # => 103.0  (with an initial value)

It reads better, and it is implemented in C so it is faster than the inject it replaces. A trivial method that you will nonetheless reach for constantly.

Regexp#match? : faster boolean matching

When you only want to know whether a string matches a pattern — not capture anything — the old idioms (=~, match) do extra work: they set the global match variables ($~, $1, …) and allocate a MatchData object. Regexp#match? just returns a boolean and does none of that:

if /\A\d+\z/.match?(input)   # no MatchData allocated, no globals set
  # ...
end

In a hot loop or a validation that runs on every request, skipping the allocation and the global-variable bookkeeping is a measurable saving. It is the right tool whenever you want a yes/no answer rather than the match details.

binding.irb: a REPL anywhere

A lovely debugging addition. You can now drop binding.irb into your code to open a full IRB session at that point, with access to all local variables — like binding.pry from the popular gem, but built into Ruby itself:

def calculate(order)
  binding.irb     # execution stops here; inspect `order` interactively
  # ...
end

It is not as feature-rich as Pry, but having a real REPL-at-a-breakpoint in the standard library, with no gem to add, is genuinely useful — especially in environments where you would rather not add dependencies just to poke at a value.

The smaller additions

Rounding out the release: Comparable#clamp constrains a value to a range (n.clamp(0, 100)); Integer#digits returns the digits of a number as an array (123.digits → [3, 2, 1]); String#unpack1 returns just the first unpacked value instead of an array; and there are refinements to Float#round and string case-handling (including better Unicode case mapping). The minimum nothing-dramatic round of deprecations continues as usual.

Should you upgrade?

Yes — it is a low-risk, broadly-beneficial release. The Integer unification is mostly conceptual and backward-compatible (the aliases keep old code working), so it costs you nothing and tidies the mental model. The faster hashes are a free, broad performance win for any Ruby program, doubly so for hash-heavy Rails apps. And the new methods — sum, match?, clamp, binding.irb — are small ergonomic improvements you will adopt naturally as you write code.

The pattern of recent Ruby releases holds steady: clean up a wart that should never have been visible, make the common data structures faster for free, and add a few sharp little methods that make everyday code read better. 2.4 is an unflashy, easy upgrade — the best kind.