Ruby に let/local/my がない(らしい)ことについて [Ruby]
以前ブロックの仮引数がブロックの外側の同名の変数を指してしまうことについて書いた[1]。
でもこれは仮引数に限ったことではなくてブロックの中で使用される変数一般に言えることだ。
foo = lambda{
x = 2
}
このブロックの意味は定義された文脈で変数 x が可視であるかどうかによって変わる。
x が不可視であれば x はブロックローカルな変数だし、可視であればその x を指す(=その x を書き換える)。
だからブロックの中で使う変数は何であれそれがブロックが定義された文脈で定義済みかどうかを意識しておかなければならないということになる。
なんでこんなややこしいことになるんだろうと思ったら、良く考えたらこれは Ruby には局所変数を定義するための有標の表現―他言語でいう let, local, my―が無いせいだ(ほんとかな?)。
OCaml や Lua や Perl では何も指定せずに変数を使うということがスコープを上に辿る(ローカルになければ)ということを意味していて、局所変数とみなしたい場合にはそれぞれ明示的に let, local, my を使う。これがたぶん普通だ。Tcl のように無標の変数がローカルスコープで広いスコープに有標の表現を使う言語もあるけどいずれにせよ別の表現を割り当てている。Ruby のように表現がひとつしかなくて文脈でスコープが変わるというのが特殊なんだと思う。
ブロックの仮引数は未来のバージョンの Ruby でローカルスコープになる予定だというのをどこかで読んだんだけど、ブロックローカルな変数を導入するための表現というのも追加されるのだろうか?
2007-02-15追記: Ruby 作者のまつもと氏の先月の日記 [2] に同じ話題があった。ブロックローカルな変数を導入するための表現は導入される予定で「ブロックパラメータの後ろに「;」を置き、そこに続けた変数はブロックローカル変数」になるらしい。なんか awk みたいな…
[1] http://blog.so-net.ne.jp/rainyday/2006-10-15
[2] http://www.rubyist.net/~matz/20070112.html#p04
コメント 0