(No) fun with ranges
by Paweł Świątkowski
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
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
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