Mitsukiの魔法実験室

Mitsuki's Magic Laboratory
Since 2002.09.14

条件式中の範囲式

Posted at 2007/09/14 13:01 in Ruby

 Ruby(や Perl)の範囲式 .. は、if 等の条件文内(やスカラーコンテキスト)で使うと、条件1でONになり条件2でOFFになるという、フリップフロップのような動作をする:


% ruby -e '10.times do |i| print i if i == 3 .. i == 6 end'
3456

 しかし、範囲式をメソッドに追い出してしまうと、期待する動作をしなくなる:


% ruby -e 'def foo(i) print i if i == 3 .. i == 6 end; 10.times do |i| foo(i) end'
3

 おそらく、範囲式の状態はローカルスコープになっているため、メソッドを抜けたところで消えてしまうんじゃないかと思う(フリップフロップだけに「揮発」か?)。利にはかなってるかもしれないけど使いづらい。
 ちなみに Perl の場合はというと:


% perl -e 'for (1 .. 10) { print if $_ == 3 .. $_ == 6 };'
3456

% perl -e 'sub foo { print if $_ == 3 .. $_ == 6 }; for (1 .. 10) { foo };'
3456

 といった具合で、実に期待通りに動く(多分 closure 的に状態保持してるんだろう)。
 じゃあ Ruby でも closure にしてみればいけそうかな?:


% ruby -e 'foo = Proc.new do |i| print i if i == 3 .. i == 6 end; 10.times do |i| foo[i] end'
3456

 めでたしめでたし……?