How do I destructure a range in Ruby?
The beginning and end? I'd use:
foo = 1..2
foo.min # => 1
foo.max # => 2
Trying to use destructuring for a range is a bad idea. Imagine the sizes of the array that could be generated then thrown away, wasting CPU time and memory. It's actually a great way to DOS your own code if your range ends with Float::INFINITY
.
end
is not the same asmax
: in 1...10,end
is 10, butmax
is 9
That's because start_val ... end_val
is equivalent to start_val .. (end_val - 1)
:
start_value = 1
end_value = 2
foo = start_value...end_value
foo.end # => 2
foo.max # => 1
foo = start_value..(end_value - 1)
foo.end # => 1
foo.max # => 1
max
reflects the reality of the values actually used by Ruby when iterating over the range or testing for inclusion in the range.
In my opinion, end
should reflect the actual maximum value that will be considered inside the range, not the value used at the end of the definition of the range, but I doubt that'll change otherwise it'd affect existing code.
...
is more confusing and leads to increased maintenance problems so its use is not recommended.
You can use minmax
to destructure ranges:
min, max = (1..10).minmax
min # => 1
max # => 10
If you are using Ruby before 2.7, avoid using this on large ranges.
No, Until I am proven incorrect by Cary Swoveland, Weekly World News or another tabloid, I'll continue believing without any evidence that the answer is "no"; but it's easy enough to make.
module RangeWithBounds
refine Range do
def bounds
[self.begin, self.end]
end
end
end
module Test
using RangeWithBounds
r = (1..10)
b, e = *r.bounds
puts "#{b}..#{e}"
end
Then again, I'd just write "#{r.begin.number_to_currency}..#{r.end.number_to_currency}"
in the first place.