On Apr 1, 2006, at 2:13 PM, Mike Austin wrote:
>
> Since you bring this up, there are a few more cases where implicit  
> locals declaration causes unexpected behavior (if new to ruby that  
> is):
>
> x = 10
> (1..10).each { |i| x = x + i }  # x == 65
> x = 10
> (1..10).each { |i| x = i }  # x == 10
>
> So if you're assigning x to itself in some way, it recognizes x in  
> the enclosing scope, else it creates a new local.  That's kind of a  
> confusing rule.    Also, what if I wanted the first example to  
> create a local?  How do I refer to the toplevel `x` in the second?

The 'x' in each of those blocks references the local variable 'x'  
defined outside the block.
In neither case is a new local variable 'x' created within the  
block.  In both cases a new
local variable 'i' is created within the blocks and is only visible  
within the individual block.

Here are the rules I use to understand local variable scope and blocks:

1) Local variables *created* outside a block are visible inside the  
block.

2) Local variables *created* inside a block are *not* visible outside  
the block.

3) Block arguments behave like *local* variables *not* formal  
(method) arguments.


If you combine 1 and 2 you see that block scope is sort of a one-way  
barrier. Code inside the block can see variables created outside the  
block but not the other way around.

The third rule is the one that throws everyone because most  
programmers tend to think of block arguments as formal arguments that  
shadow any similarly named variables outside the block but this is  
incorrect (in Ruby).  Block arguments behave like *local* variables  
so if a block argument has the same name as a variable in the  
enclosing scope then a new local variable is *not* created.  On the  
other hand if there is no local variable in the enclosing scope with  
the same name then a new local variable *is* created and is only  
visible within the block (rule 2).

I believe it is rule 3) that Matz is considering changing for Ruby 2.0


Gary Wright