[ruby-core:102088] [Ruby master Bug#17537] === on ranges of strings is not consistant with include?
From:
zverok.offline@...
Date:
2021-01-14 10:21:19 UTC
List:
ruby-core #102088
Issue #17537 has been updated by zverok (Victor Shepelev).
> ranges of strings have inconsistent semantics
That's an inherent property of string ranges, and of Range in general.
Range in Ruby represents TWO things:
* sequence (enumeration) from begin to end (based on the notion of the "next value", e.g. `<Type>#succ`)
* continuous space between begin and end (based on the notion of the order, e.g. `<Type>#<=>`)
The discrepancy between two is always present (e.g. `1...3` covers `1.5` as a space, but doesn't include it as a sequence), and indeed, with Strings, it is most noticeable.
It is true, though, not only for ranges but for other string "math" too:
```ruby
str = 'b'
str < 'я' # => true
str = str.succ while str < 'я' # infinite cycle, the string will "inrease" to "z", then turns to "aa", and so on
```
That's because the notion of the "next string" is quite synthetic, it works for _some cases_, but in general, it is a very limited "convenience" feature.
On the other hand, string order is more or less generic.
It is impossible to make them fully consistent, and introducing "special" cases for "number-alike strings", for example, is unwanted.
"Versions" example was not the _main_ reason for a change, it was just a counter-example for your "1".."10" one, to show that "what's intuitive" depends on the case. (And of course, both of our "intuitive" examples are better solved with better types: mine with `Gem::Version`, yours with `Numeric`)
----------------------------------------
Bug #17537: === on ranges of strings is not consistant with include?
https://bugs.ruby-lang.org/issues/17537#change-89946
* 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:[email protected]?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>