Issue #14473 has been updated by owst (Owen Stephens).


Hi Matz!

A slightly contrived example - imagine we want to filter candidates for a new job position and harshly reject any who have a salary requirement that is not covered by our predetermined position salary range:

~~~ruby
Candidate = Struct.new(:name, :desired_salary_range)

candidates = [
  Candidate.new('Andrew', (15_000..20_500)),
  Candidate.new('John', (25_000..35_000)),
  Candidate.new('Owen', (15_000..17_500)),
  Candidate.new('Zack', (5_000..9_000)),
]

position_salary_range = (10_000..20_000)

acceptable, unacceptable = candidates.partition { |c|
  c.desired_salary_range.subrange?(position_salary_range)
}

puts "Unacceptable: #{unacceptable.map(&:name).join(',')}" # => Unacceptable: Andrew, John, Jack
puts "Acceptable: #{acceptable.map(&:name).join(',')}" # => Acceptable: Owen
~~~

Looks like I've got the job, as no-one else is acceptable! :-)

As a more serious example, in my job, we offer loans of between 1000 and 8000. We allow certain customers to top-up their loans with an additional advance (chosen from a range of possible advances), if the new loan (the top-up is considered as a new loan) will pay-off their existing loan and cover all possible additional advances. Therefore, to check if someone can top-up their loan we do something similar to:

 ~~~ruby
class Range
  def offset(n)
    (first + n..last + n)
  end
end

VALID_LOAN_VALUE_RANGE = (1000..8000)
TOP_UP_RANGE = (1..5) # For example; very unrealistic numbers

def top_up_message(existing_loan_settlement_value)
  top_up_value_range = TOP_UP_RANGE.offset(existing_loan_settlement_value)

  if top_up_value_range.subrange?(VALID_LOAN_VALUE_RANGE)
    puts "you may top-up your loan with between #{TOP_UP_RANGE.first} and #{TOP_UP_RANGE.last}!"
  else
    puts "sorry, at this stage we can't top-up your loan"
  end
end

puts top_up_message(7995) # => you may top-up...
puts top_up_message(7999) # => sorry...
~~~

N.b. this adds another useful Range method, Range#offset (which probably only makes sense for numeric ranges), would you accept a new Feature to add this method?

Finally, regarding naming, I think I now prefer overriding `cover?` to accept a Range - when I described this feature to my colleague I used the phrase "does one range cover the other?" as an intuition, and indeed, that is how it's implemented.

Please let me know your thoughts.


----------------------------------------
Feature #14473: Add Range#subrange?
https://bugs.ruby-lang.org/issues/14473#change-72133

* Author: greggzst (Grzegorz Jakubiak)
* Status: Feedback
* Priority: Normal
* Assignee: 
* Target version: 
----------------------------------------
Hi there,

I'd like to propose a method that returns true when a range that the method gets called on is a subrange of a range passed in as an argument.

Example:

~~~ ruby
(2..4).subrange?(1...4) 
=> true
(-2..2).subrange?(-1..3) 
=> false
~~~




---Files--------------------------------
0001-range.c-add-subset-superset-methods.patch (8.84 KB)
v2-0001-range.c-add-subset-superset-methods.patch (8.85 KB)
v3-0001-range.c-add-subrange-superrange-methods.patch (9.24 KB)


-- 
https://bugs.ruby-lang.org/

Unsubscribe: <mailto:ruby-core-request / ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>