[ruby-core:102068] [Ruby master Bug#17537] === on ranges of strings is not consistant with include?
From:
zverok.offline@...
Date:
2021-01-13 17:35:26 UTC
List:
ruby-core #102068
Issue #17537 has been updated by zverok (Victor Shepelev).
It was intentional.
Before 2.6, `===` was using `include?` underneath, which had some undesirable consequences:
```ruby
case '2.5.2'
when '2.5'..'2.6'
puts "It is between 2.5 and 2.6"
else
puts "It is not"
end
```
This prints `"It is between 2.6 and 2.6"` in Ruby 2.7, but prints `"It is not"` on 2.5. It seems that "logically" the former is right.
So, in Ruby 2.6, `===` [was changed to use `cover?`](https://rubyreferences.github.io/rubychanges/2.6.html#range-uses-cover-instead-of-include) -- but, somehow, not for strings.
It was considered an oversight and was [changed in 2.7](https://rubyreferences.github.io/rubychanges/2.7.html#for-string).
```ruby
case "6"
when "1".."12"
# ...
```
...is somewhat semantically "wrong" (you are expecting to strings being compared by their numeric values), but strings are tricky, and I agree there are many edge cases which can be considered "weird"/"inconsistent", there are several tickets (I don't remember the numbers by heart) complaining about strings being between the range ends, but not in the range's items list, or vice versa.
----------------------------------------
Bug #17537: === on ranges of strings is not consistant with include?
https://bugs.ruby-lang.org/issues/17537#change-89929
* Author: akim (Akim Demaille)
* Status: Open
* Priority: Normal
* ruby -v: ruby 2.7.2p137 (2020-10-01 revision 5445e04352) [x86_64-darwin18]
* Backport: 2.5: UNKNOWN, 2.6: UNKNOWN, 2.7: UNKNOWN, 3.0: UNKNOWN
----------------------------------------
Hi,
In Ruby up to 2.6 both `("1".."12").include?("6")` and `("1".."12") === "6"` were true. In 2.7 and 3.0, `include?` accepts `"6"`, but `===` does not. This was very handy in `case`s. Reading the documentation it is unclear to me whether this change was intentional.
```
$ cat /tmp/foo.rb
puts(("1".."12").include?("6"))
puts(("1".."12") === "6")
p(("1".."12").to_a)
$ ruby2.6 /tmp/foo.rb
true
true
["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"]
$ ruby2.7 /tmp/foo.rb
true
false
["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"]
$ ruby3.0 /tmp/foo.rb
true
false
["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"]
```
Cheers!
--
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>