(No) fun with ranges
by Paweł Świątkowski
08 Aug 2014
As @nerdblogpl noticed and then published, there seems to be something wrong with how ranges are handled in ruby. I decided to go on a “range trip” myself.
As we know, there are two types of ranges - inclusive and exclusive. They are supposed to provide convenience for programmer to choose which type suits better. But do they really?
OK, not so cool, but I expected that. They are quite primitive after all. Let’s try the other way.
At first it’s a big WHAAAAT?, but then I read the docs:
end → obj
Returns the object that defines the end of the range.
All right, in fact 6 really defines the end of exclusive 1...6
range, so this is cool. So I tried with last
, which, as the docs state, returns the last object in the range, or an array of the last n elements.
And that’s the real WTF. It works differently with and without arguments. And only when returning the array, it actually does what docs say. This becomes obvious when I looked at the source:
As we see, if we supply and argument to last
it converts range to array and returns last n
elements!
As Michał also noticed, there is no built-in way to convert inclusive range into exclusive or vice-versa, so if you want to compare ranges and you are not sure what type are they, you seem to have four options:
- convert them to arrays and compare
- use
x.begin == y.begin && x.last(1).first == y.last(1).first
, which converts them to arrays under the hood - tamper with
exclude_end?
in your condition - wrap them in custom class which makes sure that we use a certain type of range