Buzz Lightyear

Watch Out For nil in Ranges

Ruby 2.6 enhanced the syntax for Range to allow for infinite values at either end, therefore allowing them to be “endless”. The new syntax is described in the Ruby documentation.

RailsConf 2024

I'm co-chairing RailsConf 2024 in Detroit May 7–9. Come and join us 

This is great for representing concepts such as date ranges between some date and one anytime the future, but this new “sugared” syntax changes existing behaviour.

Ruby used to…

…raise an ArgumentError when a nil was passed into a range…

end_of_range = nil
(1..end_of_range).map { |i| do_something(i) }
#=> ArgumentError (bad value for range)

But now…

…beware that a Range ending in nil no longer throws an error, but represents an endless range.

end_of_range = nil
(1..end_of_range).map { |i| do_something(i) }
#=> infinite loop!

Why be careful?

Ruby 2.5, and earlier, already had the ability to create endless ranges, but only by using special explicit constants—such as Float::INFINITY.

Allowing nil to be considered a valid input to a range, in a language where the result of methods can often unexpectedly be nil, definitely gives us another place to make obscure mistakes.

Why not?

You don’t really have a choice here—it’s a part of the language.

But, you can protect yourself by ensuring that you check any value you pass into a Range. It isn’t seen as “good practice” to scatter nil checks in your code, but Ruby has never been about purity in its approach to object-oriented programming.

Brighton Ruby 2024

Still running UK’s friendliest, Ruby event on Friday 28th June. Ice cream + Ruby 


Last updated on May 19th, 2019 by @andycroll

An email newsletter, with one Ruby/Rails technique delivered with a ‘why?’ and a ‘how?’ every two weeks. It’s deliberately brief, focussed & opinionated.