From: zverok.offline@... Date: 2021-01-14T10:21:19+00:00 Subject: [ruby-core:102088] [Ruby master Bug#17537] === on ranges of strings is not consistant with include? 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. `#succ`) * continuous space between begin and end (based on the notion of the order, e.g. `#<=>`) 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: