I have the following code:
# Assuming each element in foo is an array.
foo.each do |bar|
zaz = bar.first
# Other code using zaz, but not modifying it.
end
Will zaz
local variable be modified on each iteration inside this loop, making it mutable? I am not sure about the behavior of Ruby here.
It depends on the code before the loop, really.
If that is all the code, then zaz
is a block-local variable, and a new zaz
variable will be created every time the loop body is evaluated.
If, however, there is a zaz
local variable in the surrounding scope, then zaz
is a free variable in the block, and since block scopes nest in their surrounding scope, the existing zaz
variable outside the block will be re-assigned over and over again, every time the block is evaluated.
You can ensure that zaz
is always treated as a block-local variable and never looked up in the surrounding scope, by explicitly declaring it as a block-local variable in the block's parameter list:
foo.each do |bar; zaz|
zaz = bar.first
end
Note, however, that your code only makes sense IFF your code is impure and mutable:
zaz
but never actually use it inside the block. So, the only way that this makes sense at all is if zaz
is a local variable in the outer scope and you are assigning it. Although in that case, your entire loop is just equivalent to zaz = foo.last.first
. each
evaluates the block only for its side-effects. Without side-effects, each
makes no sense at all, so the fact that you are using each
implies that you have side-effects. Note that the term "immutable" without additional qualification usually refers to values. When talking about "immutable variables", we usually say "immutable variable" explicitly, to make clear that we are only talking about whether or not a variable can be re-bound, not about mutating object state. Or, one could just say "constant", which is the technical term for "immutable variable" … although that term already has a specific meaning in Ruby.
each
loops often mutate the object. Each has to do something. Because each
doesn't return anything useful - it returns the array itself, It won't mutate the object if it sends every element somewhere, like to be printed on screen.
foo.each do |bar|
# do something with element like
# print it, change it, save it
end
Functional alterantive is map
foo.map { |bar| bar.something }
It returns new array which is original array processed in immutable way. Obviously you have to be careful to use immutable methods. This would not be immutable:
foo.map { |bar| bar.something! }
Here something!
does something destructive to the element of array. However I have never seen map
used like that. Use each
for something destructive.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.