Actions
Bug #20957
openRangeError on Array#values_at with negative ranges
    Bug #20957:
    RangeError on Array#values_at with negative ranges
  
Status:
Open
Assignee:
-
Target version:
-
ruby -v:
ruby 3.4.0dev (2024-12-13T10:19:31Z master 3cb79d4082) +PRISM [arm64-darwin22]
Description
[0, 1, 2, 3].values_at(10)       #=> [nil]
[0, 1, 2, 3].values_at(10..10)   #=> [nil]
[0, 1, 2, 3].values_at(-10)      #=> [nil]
[0, 1, 2, 3].values_at(-10..-10) #=> 'Array#values_at': -10..-10 out of range (RangeError)
Is this the intended behavior?
I am aware that this behavior was recently added to the documentation, but I would like to confirm whether it is the intended behavior.
        
          
          Updated by johnnyshields (Johnny Shields) 10 months ago
          
          
        
        
      
      Here are more interesting cases:
# Reverse ranges don't return values
[0, 1, 2, 3].values_at(2..3) => [2, 3]
[0, 1, 2, 3].values_at(3..2) => []
# Positive values outside range return a nil for each index
[0, 1, 2, 3].values_at(3..10) => [3, nil, nil, nil, nil, nil, nil, nil]
# Negative ranges work so long as they are in ascending order and within the range
[0, 1, 2, 3].values_at(-4..-2)  #=> [0, 1, 2]
[0, 1, 2, 3].values_at(-5..-2)  #=> RangeError
[0, 1, 2, 3].values_at(-2..-4)  #=> []
[0, 1, 2, 3].values_at(-4..-10) #=> []
[0, 1, 2, 3].values_at(-10..-4) #=> RangeError
[0, 1, 2, 3].values_at(-5..-10) #=> RangeError
# Mix of negative and positive value does something sensible, so long as it doesn't create a "reverse range"
[0, 1, 2, 3].values_at(-4..1) #=> [0, 1]
[0, 1, 2, 3].values_at(-3..1) #=> [1]
[0, 1, 2, 3].values_at(-2..1) #=> []
[0, 1, 2, 3].values_at(-2..5) #=> [2, 3, nil, nil]
I would favor adding support for reverse ranges, and possibly the nil, nil, nil behavior for out-of-bounds negative ranges, to be congruent.
        
          
          Updated by kiridaruma (Keiichiro Nishiyama) 6 months ago
          
          
        
        
      
      I found almost same behavior at Array#fill
[0,1,2,3].fill(10, -10..-5) #=> RangeError
[0,1,2,3].fill(10, -5..-3)  #=> RangeError
[0,1,2,3].fill(10, -3..3)   #=> [0, 10, 10, 10]
[0,1,2,3].fill(10, 3..10)   #=> [0, 1, 2, 10, 10, 10, 10, 10, 10, 10, 10]
I noticed while reading Ruby's C code, and it seems that the reason is due to the mistaken calling of rb_range_beg_len().
Actions