ruby-1.8 では同名でスコープの違うローカル変数を作れない

http://www.ruby-lang.org/ja/man/?cmd=view;name=%ca%d1%bf%f4%a4%c8%c4%ea%bf%f4#a.a5.ed.a1.bc.a5.ab.a5.eb.ca.d1.bf.f4

ローカル変数スコープ(クラス、モジュー ル、メソッド定義の本体)における小文字で始まる識別子への最初 の代入はそのスコープに属するローカル変数の宣言になります。

ruby では最初の代入が変数宣言となるので、
広いスコープで使われた変数名を、
狭いスコープで別の変数の名前として使うことができない。
なぜなら、2回目の代入は(宣言なしの)単なる代入として処理されるから。

同名の変数を作るのがそもそも混乱のもとになるというのは一理あるので、
この仕様がひどいとはいえない。
「一度使われた名前は別の目的に使うことができない」という原則はそれなりに合理的だ。

しかし、

x = 10
[1,2,3].each { |x| }
puts x

1
2
3
3

というように、ブロック引数内での変数さえも同じように振る舞うのはなんか嫌だ。
上記では、

x

の x が外の x だとみなされている。
これは合理的ではない。
もし、「xを1,2,3と次々と書き換える」ことを意図するなら

[1,2,3].each { |y| x=y }

と、ほとんど変わらない手間で、より明瞭に書けるからだ。

ruby-1.9 では
このようなブロック内の変数はブロックローカル変数として独立した変数になるようになった。
http://eigenclass.org/hiki/Changes+in+Ruby+1.9#l7

(2008-01-20T22:40:42+0900)
そもそも、ruby-1.8 のローカル変数スコープはメソッドごとにひとつづつしかなかった。
ruby-1.9 ではブロックローカル変数スコープが新設され、
ブロック引数はそのスコープを作ることになった。

……という理解が正しいようだ。