3

I'm working on the about_arrays.rb file within Ruby Koans and I noticed this piece of code and I'm not sure why the answer is what it is:

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

  assert_equal [], array[4,0]
  assert_equal [], array[4,100]
  assert_equal nil, array[5,0]
end

Based on the output for Ruby Koans, can someone explain to me why array[4,0] would evaluate to [] while array[5,0] evaluates to nil?. Why wouldn't array[5,0] also evaluate to []?

Out of curiosity, I tried array[6,0], array[7,0], and so on and also got nil. Is there something special that Ruby does for the array index next in line to get something appended to it?


EDIT:

I found "Array slicing in Ruby: looking for explanation for illogical behaviour (taken from Rubykoans.com)", which asks the same question, but I'm still not understanding how indices work in array slicing.

Community
  • 1
  • 1
wmock
  • 5,382
  • 4
  • 40
  • 62

1 Answers1

6

The s[n, 0] defines a place just before or after a character, and often before one and after another.

Source.

The first argument to the slice is the lower bound. When it's 4, it is still part of the array, just pointing to the very end. When the lower bound is beyond the length of the array, it's always nil.

It's best to think of the offsets of the spaces between the element values.

RubyFiddle.

alex
  • 479,566
  • 201
  • 878
  • 984
  • Why would the lower bound be 4? Aren't the array indices from 0 to 3? – wmock Feb 25 '13 at 01:33
  • @WillsonMock indexes != slice boundaries. See the link. – alex Feb 25 '13 at 01:34
  • Sorry, this still isn't clear to me yet. When you're referring to boundaries in arrays, are you not referring to the first and last indicies of the array? – wmock Feb 25 '13 at 01:40
  • 1
    @WillsonMock I just added a RubyFiddle to help explain it. When you slice from `3,4`, you're getting the last element in that array, so you can see that `4` is a valid boundary. So if you start the slice at `4`, you're pointing to the end of the array, and slicing `0` elements from there will get you back an empty array. Someone might have a better way of explaining it than me. :) – alex Feb 25 '13 at 01:41
  • 1
    @WillsonMock *"Empty slice"* serves for insertion instead of replacement when Array as l-value expression. So `array[4,0]=object` **inserts** object *after* the the last element, `array[3,0]=object` would insert object *before* the last element etc. Non-empty slice would **replace** elements. – David Unric Feb 25 '13 at 01:46
  • @alex the empty slice always defines a place *before* the starting index, so the place after the last element has to be indexed with *(index of last element + 1)*. – David Unric Feb 25 '13 at 01:58