Splicing Arrays

"Ghost in the Shell"

Merry Christmas and happy holidays. Lately, I have been digging deeper to understand core Ruby principles away from web development. One of the tools that I am using are are the Ruby Koans – a set of fun, challenging problems that build on each other as your progress through levels. As such, solving these problems is a great way to learn about Ruby syntax, and under-the-hood Rubyisms.

I was working through a section in the Koans called “about_arrays”, specifically test_slicing_arays.

For example:

about_arrays.rb
1
2
3
4
5
6
7
8
9
10
11
def test_slicing_arrays
  array = [:peanut, :butter, :and, :jelly]

  assert_equal __, array[0,1]
  assert_equal __, array[0,2]
  assert_equal __, array[2,2]
  assert_equal __, array[2,20]
  assert_equal __, array[4,0]
  assert_equal __, array[4,100]
  assert_equal __, array[5,0]
end

In this example, an array is defined and includes four symbols; peanut, butter, and, jelly. There are a number of assertions to be made. Where the underscore exists, the user submits their answer. For exampl:

about_arrays.rb
1
2
3
4
5
6
7
8
9
10
11
def test_slicing_arrays
  array = [:peanut, :butter, :and, :jelly]

  assert_equal [:peanut], array[0,1]
  assert_equal [:peanut, :butter], array[0,2]
  assert_equal [:and, :jelly], array[2,2]
  assert_equal [:and, :jelly], array[2,20]
  assert_equal [], array[4,0]
  assert_equal [], array[4,100]
  assert_equal nil, array[5,0]
end

The first argument accepts the “lower bound”, while the second argument is the “range of elements” that you want to pull out of the array, beginning with the “lower bound”. So going through the list, I understood up until the last line: ruby assert_equal nil, array[5,0].

So, really, I didn’t understand anything. After a lot of stackoverflow searching, I came across this post.

What is exactly happening here?

In my head, how I thought indices and arrays worked was this:

1
2
  :peanut   :butter   :and   :jelly
     0         1        2       3

Following from this logic, then [], array [4,0] also wouldn’t make sense, yet that is the solution. Swoon

According to the way splicing works, the indices are defined more like the following:

1
2
  :peanut   :butter   :and   :jelly
0         1         2      3        4

It’s now worth noting that finding the range of an array is different than finding index. When an array is spliced, as in array[4,0], the splice does not identify the elements themselves, but places BETWEEN the elements. This is a key distinction from array[4]; here, Ruby is pointing at index 4. This would result in nil. Try it for yourself!

Simply put: slicing and indexing are different operations, and as such, include different operations, and shouldn’t be directly compared.