简体   繁体   English

Ruby循环局部变量和不变性

[英]Ruby loop local variables and inmutability

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? 是否会在此循环内的每次迭代中修改zaz局部变量,使其可变? I am not sure about the behavior of Ruby here. 我不确定Ruby的行为。

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. 如果这就是全部代码,则zaz是块局部变量,并且每次评估循环体时都将创建一个新的 zaz变量。

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. 但是,如果周围范围中有zaz局部变量,则zaz是块中的自由变量,并且由于块范围嵌套在其周围范围中,因此,将zaz重新分配该块外部的现有zaz变量再次,每次评估块。

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: 通过在块的参数列表中明确将其声明为块局部变量,可以确保zaz始终被视为块局部变量,并且永远不会在周围的范围中查找:

foo.each do |bar; zaz|
  zaz = bar.first
end

Note, however, that your code only makes sense IFF your code is impure and mutable: 但是请注意,你的代码才有意义IFF你的代码是不纯的和可变的:

  1. You assign to zaz but never actually use it inside the block. 您分配给zaz但从未在块内实际使用它。 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. 因此,这唯一有意义的唯一方法是zaz是外部作用域中的局部变量,并且您正在分配它。 Although in that case, your entire loop is just equivalent to zaz = foo.last.first . 尽管在这种情况下,您的整个循环仅等效于zaz = foo.last.first
  2. each evaluates the block only for its side-effects. each仅评估其副作用。 Without side-effects, each makes no sense at all, so the fact that you are using each implies that you have side-effects. 没有副作用, each副作用就完全没有意义,因此您正在使用each副作用这一事实意味着您有副作用。

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. 或者,可以只说“常量”,这是“不可变变量”的技术术语……尽管该术语在Ruby中已经具有特定的含义。

each loops often mutate the object. each循环通常会使对象变异。 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. 因为each元素都不会返回任何有用的信息-它会返回数组本身,所以如果将每个元素发送到某个地方(例如在屏幕上打印),它都不会使对象发生变异。

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! 在这里something! does something destructive to the element of array. 对数组元素有破坏性。 However I have never seen map used like that. 但是我从未见过像那样使用过的map Use each for something destructive. 使用each破坏性的东西。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM