mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
Merge pull request #4560 from lopopolo/range-max-min-hang
Specialize Enumerable#max and Enumerable#min for Range
This commit is contained in:
@@ -25,4 +25,43 @@ class Range
|
||||
end
|
||||
ary
|
||||
end
|
||||
|
||||
def max(&block)
|
||||
val = self.first
|
||||
last = self.last
|
||||
return super if block
|
||||
|
||||
# fast path for numerics
|
||||
if (val.kind_of?(Fixnum) || val.kind_of?(Float)) && (last.kind_of?(Fixnum) || last.kind_of?(Float))
|
||||
raise TypeError if exclude_end? && !last.kind_of?(Fixnum)
|
||||
return nil if val > last
|
||||
return nil if val == last && exclude_end?
|
||||
|
||||
max = last
|
||||
max -= 1 if exclude_end?
|
||||
return max
|
||||
end
|
||||
|
||||
# delegate to Enumerable
|
||||
super
|
||||
end
|
||||
|
||||
def min(&block)
|
||||
val = self.first
|
||||
last = self.last
|
||||
return super if block
|
||||
|
||||
# fast path for numerics
|
||||
if (val.kind_of?(Fixnum) || val.kind_of?(Float)) && (last.kind_of?(Fixnum) || last.kind_of?(Float))
|
||||
raise TypeError if exclude_end? && !last.kind_of?(Fixnum)
|
||||
return nil if val > last
|
||||
return nil if val == last && exclude_end?
|
||||
|
||||
min = val
|
||||
return min
|
||||
end
|
||||
|
||||
# delegate to Enumerable
|
||||
super
|
||||
end
|
||||
end
|
||||
|
||||
@@ -30,3 +30,105 @@ assert('Range#size') do
|
||||
assert_equal Float::INFINITY, (0..Float::INFINITY).size
|
||||
assert_nil ('a'..'z').size
|
||||
end
|
||||
|
||||
assert('Range#max') do
|
||||
# returns the maximum value in the range when called with no arguments
|
||||
assert_equal 10, (1..10).max
|
||||
assert_equal 9, (1...10).max
|
||||
assert_equal 4294967295, (0...2**32).max
|
||||
|
||||
# returns the maximum value in the Float range when called with no arguments
|
||||
assert_equal 908.1111, (303.20..908.1111).max
|
||||
|
||||
# raises TypeError when called on an exclusive range and a non Integer value
|
||||
assert_raise(TypeError) { (303.20...908.1111).max }
|
||||
|
||||
# returns nil when the endpoint is less than the start point
|
||||
assert_equal nil, (100..10).max
|
||||
|
||||
# returns nil when the endpoint equals the start point and the range is exclusive
|
||||
assert_equal nil, (5...5).max
|
||||
|
||||
# returns the endpoint when the endpoint equals the start point and the range is inclusive
|
||||
assert_equal 5, (5..5).max
|
||||
|
||||
# returns nil when the endpoint is less than the start point in a Float range
|
||||
assert_equal nil, (3003.20..908.1111).max
|
||||
end
|
||||
|
||||
assert('Range#max given a block') do
|
||||
# passes each pair of values in the range to the block
|
||||
acc = []
|
||||
(1..10).max do |a, b|
|
||||
acc << a
|
||||
acc << b
|
||||
a
|
||||
end
|
||||
(1..10).each do |value|
|
||||
assert_true acc.include?(value)
|
||||
end
|
||||
|
||||
# passes each pair of elements to the block in reversed order
|
||||
acc = []
|
||||
(1..5).max do |a, b|
|
||||
acc << [a, b]
|
||||
a
|
||||
end
|
||||
assert_equal [[2, 1], [3, 2], [4, 3], [5, 4]], acc
|
||||
|
||||
# returns the element the block determines to be the maximum
|
||||
assert_equal 1, ((1..3).max { |_a, _b| -3 })
|
||||
|
||||
# returns nil when the endpoint is less than the start point
|
||||
assert_equal nil, ((100..10).max { |x, y| x <=> y })
|
||||
assert_equal nil, ((5...5).max { |x, y| x <=> y })
|
||||
end
|
||||
|
||||
assert('Range#min') do
|
||||
# returns the minimum value in the range when called with no arguments
|
||||
assert_equal 1, (1..10).min
|
||||
assert_equal 1, (1...10).min
|
||||
|
||||
# returns the minimum value in the Float range when called with no arguments
|
||||
assert_equal 303.20, (303.20..908.1111).min
|
||||
|
||||
# returns nil when the start point is greater than the endpoint
|
||||
assert_equal nil, (100..10).min
|
||||
|
||||
# returns nil when the endpoint equals the start point and the range is exclusive
|
||||
assert_equal nil, (5...5).max
|
||||
|
||||
# returns the endpoint when the endpoint equals the start point and the range is inclusive
|
||||
assert_equal 5, (5..5).max
|
||||
|
||||
# returns nil when the start point is greater than the endpoint in a Float range
|
||||
assert_equal nil, (3003.20..908.1111).max
|
||||
end
|
||||
|
||||
assert('Range#min given a block') do
|
||||
# passes each pair of values in the range to the block
|
||||
acc = []
|
||||
(1..10).min do |a, b|
|
||||
acc << a
|
||||
acc << b
|
||||
a
|
||||
end
|
||||
(1..10).each do |value|
|
||||
assert_true acc.include?(value)
|
||||
end
|
||||
|
||||
# passes each pair of elements to the block in reversed order
|
||||
acc = []
|
||||
(1..5).min do |a, b|
|
||||
acc << [a, b]
|
||||
a
|
||||
end
|
||||
assert_equal [[2, 1], [3, 1], [4, 1], [5, 1]], acc
|
||||
|
||||
# returns the element the block determines to be the minimum
|
||||
assert_equal 3, ((1..3).min { |_a, _b| -3 })
|
||||
|
||||
# returns nil when the start point is greater than the endpoint
|
||||
assert_equal nil, ((100..10).min { |x, y| x <=> y })
|
||||
assert_equal nil, ((5...5).min { |x, y| x <=> y })
|
||||
end
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
assert('Range#max') do
|
||||
# returns the maximum value in the range when called with no arguments
|
||||
assert_equal 'l', ('f'..'l').max
|
||||
assert_equal 'e', ('a'...'f').max
|
||||
|
||||
# returns nil when the endpoint is less than the start point
|
||||
assert_equal nil, ('z'..'l').max
|
||||
end
|
||||
|
||||
assert('Range#max given a block') do
|
||||
# returns nil when the endpoint is less than the start point
|
||||
assert_equal nil, (('z'..'l').max { |x, y| x <=> y })
|
||||
end
|
||||
|
||||
assert('Range#min') do
|
||||
# returns the minimum value in the range when called with no arguments
|
||||
assert_equal 'f', ('f'..'l').min
|
||||
|
||||
# returns nil when the start point is greater than the endpoint
|
||||
assert_equal nil, ('z'..'l').min
|
||||
end
|
||||
|
||||
assert('Range#min given a block') do
|
||||
# returns nil when the start point is greater than the endpoint
|
||||
assert_equal nil, (('z'..'l').min { |x, y| x <=> y })
|
||||
end
|
||||
Reference in New Issue
Block a user