Project

General

Profile

Feature #12612

Switch Range#=== to use cover? instead of include?

Added by zverok (Victor Shepelev) about 3 years ago. Updated over 2 years ago.

Status:
Rejected
Priority:
Normal
Assignee:
-
Target version:
-
[ruby-core:76529]

Description

Currently, Range#=== is an alias of #include?, which works by #each-ing all the values and comparing them to the checked value. It may lead to fascinating inefficiencies, when working with strings or other similar classes (for example, IP class for allowing/disallowing IP ranges). Moreover, it is not consistent with behavior of numerical ranges (which is kinda special case, I guess):

(1...3) === 2.5 # true - though (1..3).to_a.include?(2.5) is false
('a'...'z') === 'foo' # false - because ('a'..'z').to_a.include?('foo') is false

As === is heavily used in case and grep, and there is no option to replace it manually with cover? there, maybe it would be reasonable to change the behavior?

To be honest, I could imagine no real cases when include? is preferable for identity check.


Related issues

Related to Ruby master - Feature #12996: Optimize Range#===OpenActions
Has duplicate Ruby master - Feature #14575: Switch Range#=== to use cover? instead of include?ClosedActions

History

Updated by zverok (Victor Shepelev) almost 3 years ago

Did anybody saw this?..

Updated by matz (Yukihiro Matsumoto) over 2 years ago

  • Status changed from Open to Rejected

I see no real-world use-case for Range#=== with strings.
Besides that, using cover? behavior for string ranges would introduce incompatibility.

Matz.

Updated by zverok (Victor Shepelev) over 2 years ago

I encountered the problem in production code, it was not strings, but specialized IPAddress class, to filter "if IP is in range" -- it was SUDDENLY 0.4 sec on each request to server spent just to (IPAddress.new(from)..IPAddress.new(to)).to_a in "innocently" looking:

case ip
when admin_ip_range
...

Another real cases:

Yes, proposed behavior is incompatible with current, but I am not sure it is a bad thing:

(Date.parse('2016-05-01')..Date.today) === DateTime.parse('2016-06-01 12:30')
# => false 
(Date.parse('2016-05-01')..Date.today).cover?(DateTime.parse('2016-06-01 12:30'))
# => true 

# Which is more logical? What you'll intuitively expect here:
case DateTime.parse('2016-06-01 12:30')
when Date.parse('2016-05-01')..Date.today
  # looks like we SHOULD be here, but... 
#4

Updated by shyouhei (Shyouhei Urabe) over 2 years ago

#5

Updated by matz (Yukihiro Matsumoto) over 1 year ago

  • Related to Feature #14575: Switch Range#=== to use cover? instead of include? added
#6

Updated by matz (Yukihiro Matsumoto) over 1 year ago

  • Related to deleted (Feature #14575: Switch Range#=== to use cover? instead of include?)
#7

Updated by matz (Yukihiro Matsumoto) over 1 year ago

  • Has duplicate Feature #14575: Switch Range#=== to use cover? instead of include? added

Also available in: Atom PDF