Reputation: 8588
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
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
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