Severin
Severin

Reputation: 8588

Loop resets variable

I am encountering the following unexpected behavior while running the following loop:

outside_var = 'myString'
loop do
  inside_var ||= outside_var
  result = SomeCalculation.do_something(inside_var)
  inside_var = result[:new_inside_var_value]
end

Now, on the first iteration inside_var gets set to outside_var, which is the expected behavior. Just before the next iteration I set inside_var to something else (depending on the result I got from the calculation inside the loop). This assignment works (printing inside_var at the very bottom of the loop confirms that). On the next iteration, however, inside var goes back to the original state, which is something I didn't anticipate. Why is it doing that and how can I set this variable inside this loop?

I am running Ruby 2.6.5 with Rails 6.

Upvotes: 1

Views: 357

Answers (2)

Aleksei Matiushkin
Aleksei Matiushkin

Reputation: 121000

This is a scoping issue. inside_var is scoped to the block. One might check the binding, it changes.

outside_var = 'myString'
2.times do
  puts "INSIDE 1: #{defined?(inside_var).nil?} → #{binding}"
  inside_var ||= outside_var
  puts "INSIDE 2: #{inside_var}"
end
#⇒ INSIDE 1: true → #<Binding:0x000055a3936ee0b0>
#  INSIDE 2: myString
#  INSIDE 1: true → #<Binding:0x000055a3936edc50>
#  INSIDE 2: myString

That said, every time the execution enters the block, the binding is reset, that’s why one should not expect the variables from another scope (with another binding) to exist.

Upvotes: 1

L. C
L. C

Reputation: 106

When you do a new iteration inside the loop, you are going to reset everything. I suggest you to modify the var outside the loop to preserve the value inside. Something like this:

result_var = 'myString' # value on the first iteration
loop do
  result = SomeCalculation.do_something(result_var)
  result_var = result[:new_inside_var_value] # at the end of the first iteration you are already overriding this value
end

Upvotes: 0

Related Questions