Arrays of Arrays: Referencing

Learn how to make different references to arrays so that they point to different objects in Ruby.

Referencing

The answer to why all the array elements get updated when we modify one element of the array can be found in the concept of a reference. When initializing an array, we pass the reference to a single object:

arr = Array.new(10, 'something')

something above is a String object, since everything is an object in Ruby. Since we’re passing the reference to this single object, the array will get initialized with 10 cells, each with the same reference value. In other words, there is no object inside a cell. There is only a reference to an object.

To avoid this side effect, we need these references to be different, so that they point to different objects. These objects will be placed at different locations in computer memory, but technically they will look the same.

It’s like having the same type of beer in your six-pack: all the bottles look the same, but they’re all different bottles. If we change the state of one bottle, it won’t affect the state of the other bottles.

With the example of an apartment complex with multiple doorbells, imagine the following scenario. We brought a box—an array—and we want to put 10 doorbells inside that box. We did that, but all the wires led to only one specific apartment. It doesn’t matter which doorbell we use, because we’ll only get an answer from the same tenants of that one apartment.

The right way

If we want to fix this mistake, we will need these wires to lead to different apartments. Always avoid code like this:

arr = Array.new(10, []) # <-- WRONG!

It’s wrong because the array inside is supposed to change its state. Why would we need an empty array? There is no sense in that, because we’ll eventually want to add something to that empty array. That is exactly what arrays were created for. But with strings, things are easier, and the following code works:

arr = Array.new(10, 'something')

But with one caveat: We will not use a “dangerous” operation on a string or any other data type. A dangerous operation can change the state of an object and, usually, these methods have an exclamation mark at the end, as seen in 'something'.upcase!. Do you understand why these methods are called “dangerous”?

We’re safe to define arrays with numbers:

arr = Array.new(10, 123)

There are no “dangerous” methods on the Integer class. Even if we can access the array, we can’t modify it and we can’t change its state. We can only replace one object with another, but that won’t cause the previous object to disappear. It will remain in computer memory for a while until the garbage collector finds it.

So, if we type arr[4] = 124, we’ll replace the reference in the array with another reference leading to a new object (124). And all the other references to the previous 123 object will remain untouched.

With numbers, we’re getting what we expected:

Get hands-on with 1200+ tech skills courses.