我有以下代码:
# Assuming each element in foo is an array.
foo.each do |bar|
zaz = bar.first
# Other code using zaz, but not modifying it.
end
在此循环内的每次迭代中是否会修改zaz
局部变量,使其变为可变?我不确定Ruby的行为。
答案 0 :(得分:4)
这取决于循环之前的代码,真的。
如果那是 all 代码,那么zaz
是一个块本地变量,每个都会创建一个 new zaz
变量评估循环体的时间。
但是,如果周围范围中存在zaz
局部变量,则zaz
是块中的自由变量,并且由于块范围嵌套在其周围范围内,因此现有zaz
每次对块进行求值时,块内外的变量将反复重新分配。
您可以确保zaz
始终被视为块局部变量,并且永远不会在周围范围内查找,方法是在块的参数列表中将其明确声明为块局部变量:
foo.each do |bar; zaz|
zaz = bar.first
end
但请注意,您的代码只有正确 IFF 您的代码不纯净且可变:
zaz
但从未在块内实际使用它。因此,唯一有意义的方法是,zaz
是外部作用域中的局部变量,并且您正在分配它。虽然在这种情况下,您的整个循环只相当于zaz = foo.last.first
。each
仅针对其副作用评估该块。没有副作用,each
完全没有意义,所以你使用each
的事实暗示你有副作用。注意术语"不可变"没有额外资格通常是指价值观。在谈论"不可变变量"时,我们通常会说"不可变变量"显式地,明确我们只讨论变量是否可以重新绑定,而不是变异对象状态。或者,可以说"常数",这是"不可变变量"的技术术语。 ......虽然这个术语在Ruby中已经具有特定含义。
答案 1 :(得分:1)
each
循环经常改变对象。每个人都必须做点什么。
因为each
没有返回任何有用的东西 - 它返回数组本身,如果它在某个地方发送每个元素,它就不会改变对象,就像在屏幕上打印一样。
foo.each do |bar|
# do something with element like
# print it, change it, save it
end
功能变化是地图
foo.map { |bar| bar.something }
它返回新数组,它是以不可变方式处理的原始数组。显然你必须小心使用不可变方法。这不是一成不变的:
foo.map { |bar| bar.something! }
这里something!
会对数组元素造成破坏性影响。
但是我从来没有见过map
那样的用法。使用each
来破坏性的东西。