1

If I use an each do loop to fill an array, it will leave the array as it is (in this case it will be a nil array of size 4)

array = Array.new(4)
array.each do |i|
  i = 5
end

I understand that I can initialize an array with my desired value using array = Array.new(4) {desired value} but there are situations in which I'm choosing between different values and I am trying to understand how the each do loop work exactly.

The current way I'm doing it is the following which fills in the array with my desired value

array = Array.new(4)
array.each_with_index do |val, i|
  array[i] = 5
end
2
  • You could alternatively pass in a second parameter to fill in the array, as such: array = Array.new(4, 5) which will achieve the same effect. Commented Jan 3, 2017 at 11:19
  • This is another example of someone getting confused by people insisting that Ruby is pass-by-reference. No, it isn't! It is pass-by-value. If it were pass-by-reference, the OP's code would work. I am at a loss as to why this is so controversial. Can we please just stop confusing people by claiming Ruby is pass-by-reference? Commented Jan 3, 2017 at 14:45

2 Answers 2

4

Solution

You need :

array = Array.new(4) do |i|
  5
  # or some logic depending on i (the index between 0 and 3)
end

Your code

array = Array.new(4)

array is now an Array with 4 elements (nil each time).

array.each iterates over those 4 elements (still nil), and sets i as block-local variable equal to nil.

Inside this block, you override i with 5, but you don't do anything with it. During the next iteration, i is set back to nil, and to 5, and so on...

You don't change the original array, you only change local variables that have been set equal to the array elements.

Sign up to request clarification or add additional context in comments.

Comments

3

The difference is that

i = 5

is an assignment. It assigns the value 5 to the variable i.

In Ruby, assignments only affect the local scope, they don't change the variable in the caller's scope:

def change(i)
  i = 5       # <- doesn't work as you might expect
end

x = nil
change(x)
x #=> nil

It is therefore impossible to replace an array element with another object by assigning to a variable.

On the other hand,

array[i] = 5

is not an assignment, but a disguised method invocation. It's equivalent to:

array.[]=(i, 5)

or

array.public_send(:[]=, i, 5)

It asks the array to set the element at index i to 5.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.