Project

General

Profile

Feature #19588

Updated by kyanagi (Kouhei Yanagita) about 1 year ago

`Comparable#clamp(min, max)` (with two arguments) accepts `nil`. This behaves the same as beginless/endless Range. 

 ~~~ruby 
 5.clamp(nil, 0)     # => 0 
 5.clamp(10, nil)    # => 10 
 5.clamp(..0)        # => 0 
 5.clamp(10..)       # => 10 
 ~~~ 

 This behavior is not documented. Presumably, this was not introduced intentionally. 

 The old Rubies did not accept accept a `Range` argument. 

 In Ruby 2.7, accepting `Range` as an argument was introduced. 
 At that time, the approach of passing `nil` as a two-argument method was also discussed but not adopted, 
 and using Range was chosen instead. https://bugs.ruby-lang.org/issues/14784 

 However, in Ruby 3.0, the behavior of `clamp` has changed to accept `nil`. 
 This change is not documented in the NEWS or the documentation for `clamp`, 
 and I believe that it was not an intentional change. 

 ~~~ 
 % docker run -it --rm rubylang/all-ruby env ALL_RUBY_SINCE=ruby-2.4.0 ./all-ruby -e "p 5.clamp(0, nil)" 
 ruby-2.4.0            -e:1:in `clamp': comparison of Integer with nil failed (ArgumentError) 
                         from -e:1:in `<main>' 
                 exit 1 
 ... 
 ruby-2.7.8            -e:1:in `clamp': comparison of Integer with nil failed (ArgumentError) 
                         from -e:1:in `<main>' 
                 exit 1 
 ruby-3.0.0-preview1 5 
 ... 
 ruby-3.2.2            5 
 ~~~ 

 It seems that https://github.com/ruby/ruby/commit/a93da4970be44a473b7b42e7516eb2663dece2c3 brought about this change. 

 How about making the current behavior a specification? 
 It has been three years since the behavior changed, and I don't see much point in prohibiting `nil` now. 

 https://github.com/ruby/ruby/pull/7692 updates the documentation. 

Back