From: "knu (Akinori MUSHA) via ruby-core" Date: 2023-03-17T08:58:25+00:00 Subject: [ruby-core:112927] [Ruby master Bug#19533] Behavior of ===/include? on a beginless/endless range (nil..nil) changed in ruby 3.2 Issue #19533 has been updated by knu (Akinori MUSHA). mame (Yusuke Endoh) wrote in #note-2: > In #18580, @matz said: > > > I decided to make `include?` to raise exception for beginless/endless non-numeric ranges. > > and `(nil..nil)` is considered as a non-numeric range. Thanks for the info. This hurts not only because the behavior changed without notice (in the NEWS file) but because it broke the useful feature. Before the change, you could just say `scores.grep(min..max)` when `min` and `max` are both optional, but now you need to check if `min` and `max` are both nil and branch the logic. While `(nil..nil) === value` (used in `case`, `Enumerable#grep`, `any?`, etc.) no longer works, ActiveRecord queries like `Product.where(price: min..max)` still work because `===` is not used there. This is a bit confusing and hard to explain why. I'm not absolutely sure about `include?`, but as for `===` I'd like the previous behavior to be restored because it was so useful and aligned with `cover?`, and changing back wouldn't break existing code because the current behavior is to raise an error rather than returning false. ---------------------------------------- Bug #19533: Behavior of ===/include? on a beginless/endless range (nil..nil) changed in ruby 3.2 https://bugs.ruby-lang.org/issues/19533#change-102447 * Author: knu (Akinori MUSHA) * Status: Open * Priority: Normal * Target version: 3.2 * ruby -v: ruby 3.2.1 (2023-02-08 revision 31819e82c8) [x86_64-darwin22] * Backport: 2.7: UNKNOWN, 3.0: UNKNOWN, 3.1: UNKNOWN, 3.2: UNKNOWN ---------------------------------------- Starting from Ruby 2.7.0 a range `nil..nil` used to match any value until 3.2.0-preview3, but 3.2.0-rc1 started to reject it. ``` % docker run -it --rm rubylang/all-ruby ./all-ruby -e 'p( (nil..nil) === 1 )' (snip) ruby-2.6.10 false ruby-2.7.0-preview1 true ... ruby-3.2.0-preview3 true ruby-3.2.0-rc1 -e:1:in `===': cannot determine inclusion in beginless/endless ranges (TypeError) p( (nil..nil) === 1 ) ^ from -e:1:in `
' exit 1 ... ruby-3.2.1 -e:1:in `===': cannot determine inclusion in beginless/endless ranges (TypeError) p( (nil..nil) === 1 ) ^ from -e:1:in `
' ``` The previous behavior was so useful because when you have optional lower and upper bounds `lbound..rbound` would always work regardless of each end being nil or not. There is no mention of this in doc/NEWS/NEWS-3.2.0.md, so I'm afraid it was caused unintentionally while fixing other problems. ``` % docker run -it --rm rubylang/all-ruby ./all-ruby -e 'p( (nil..nil).cover?(1) )' (snip) ruby-2.6.10 false ruby-2.7.0-preview1 true ... ruby-3.2.1 true ``` This was pointed out by the following blog article (written in Japanese) as a "pitfall" that you need to work around when upgrading Ruby from 3.0/3.1 to 3.2. https://blog.studysapuri.jp/entry/2023/03/16/ujihisa-ruby32#endless-range%E3%81%AE%E6%8C%99%E5%8B%95%E3%81%AE%E5%A4%89%E6%9B%B4 -- https://bugs.ruby-lang.org/ ______________________________________________ ruby-core mailing list -- ruby-core@ml.ruby-lang.org To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org ruby-core info -- https://ml.ruby-lang.org/mailman3/postorius/lists/ruby-core.ml.ruby-lang.org/