2007-03-07 (水) [長年日記]
_ アナログテレビ最大6400万台がゴミに 地デジ移行で
何をいまさら。最初から分かっていたことじゃないか。
_ イテレータ引数がブロック外の変数を上書きする
$ ruby -e 'a=0;[1].each{|a|};p a' 1
|a| はブロック内でしか使われないので、ブロック外の変数を汚染するのは感覚的に変だと思うんだが。
ブロックの先頭に、仮引数を||で囲って置くと、実引数が多重代入されます。この仮引数は、普通のローカル変数で、ブロックの外側ですでに使われている変数の場合は、そのスコープになりますので、注意が必要です。
Rubyを始めたばかりの時にハマりました。 > イテレータ引数がブロック外の変数を上書きする
FAQになってるってことは、この仕様で問題ないという判断なんですかねぇ。
ブロックローカルの変数をどうするかという問題と一緒に議論されたことがあると思います。<br>記述を工夫するとか幾つか案は出ましたが決定打は出ませんでした。<br>ということで、現状の仕様で問題ないとはまつもとさんも考えてはいないと思います。<br>上記の議論はruby-devあたりだったと思いますが、具体的な番号は<br>わかりません。ごめんなさい。
イテレータ変数がブロック外の変数を上書きしたほうがいい(または上書きせざるをえない)理由が思いつかないのですが…。
えと、狙って今の仕様(同じ名前で上書き発生)にしたのではなく、<br>結果としてそうなってしまっているというものだと記憶しています。<br>理由としては「やりやすい実装でやってみたらそういう動作になってしまった」<br>くらいのところでしょうか?
とりあえずこんなところ → http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-dev/17487 <br>が見つかりました。<br>元発言をたどっていけばそれなりにボリュームがあります。<br>あと、http://takkan-m.katamayu.net/tdiary/index.rb?date=20061112 <br>のコメント欄でささださんが<br>> 1.9 から、ブロックパラメータ(|a|)はブロックローカル変数になるらしいですよ。<br>と書いてます。<br>#この話の記憶はないなあ…蒸発したか?
何度もすみません。ささださんが某所で1.9ではブロック変数の扱いが変わってるよとコメントしているのを見つけたので確認してみました。<br>puts RUBY_VERSION<br>x=1<br>puts "x=#{x}"<br>(1..5).to_a.each{|x| puts x}<br>puts "x=#{x}"<br>こんなスクリプトでやってみましたが、1.9では確かに<br>最後のputsでの出力がx=1になります(1.8では5)。
手元に 1.9 が無いので試せませんが、修正されてるなら嬉しいことです。ありがとうございました。