0

Possible Duplicate:
Array slicing in Ruby: looking for explanation for illogical behaviour (taken from Rubykoans.com)

I have a simple array object:

array = [:peanut, :butter, :and, :jelly]

Its length is, clearly, 4!

Now, take a look at these statements:

array[4,0] == []
array[5,0] == nil

Slicing the array from 4th index, it returns an empty array, but starting from 5th element, it returns nil. Why this happens?

Community
  • 1
  • 1
Mich Dart
  • 2,352
  • 5
  • 26
  • 44

3 Answers3

1

slice(start, length) (which is the method called when you access array[]) returns an array of length length starting at index start. This explains why array[4,0] return [].

However, there is a corner case in this method. The Ruby documentation of slice says:

Returns nil if the index (or starting index) are out of range.

In your second example, 5 is out of range for array. This causes the method to return nil.

Vivien Barousse
  • 20,555
  • 2
  • 63
  • 64
1

For a second, I thought you had found a bug, but I think I can explain this behaviour. The starting index you give to slice is considered just before the element at that index. So index 4 is considered the very end of the array (just before index 4, just after index 3). The following examples should make it clear:

> [1,2,3,4][0, 3]
 # => [1, 2, 3] 
> [1,2,3,4][1, 3]
 # => [2, 3, 4] 
> [1,2,3,4][2, 3]
 # => [3, 4] 
> [1,2,3,4][3, 3]
 # => [4] 
> [1,2,3,4][4, 3]
 # => [] 
> [1,2,3,4][5, 3]
 # => nil 
tsherif
  • 11,502
  • 4
  • 29
  • 27
1

Actually, the reason for things you found "strange" should always lie in source code. I just pick the relevant snippet from https://github.com/ruby/ruby/blob/trunk/range.c

...
if (beg < 0) {
beg += len;
if (beg < 0)
    goto out_of_range;
}
if (err == 0 || err == 2) {
if (beg > len)
    goto out_of_range;
if (end > len)
    end = len;
}
...

Here, if starting index beg is smaller than -length, it returns out of range Qnil. Otherwise, if starting index is larger than length of array (len in code snippet), it returns out of range (Qnil) too. NOTICE here, it's larger than not larger or equal than, that's why you get [] for array[4,0] (although 4 is out of range) but nil for array[5,0]

Tomato
  • 438
  • 2
  • 7