前回の話でちょっと出した、残念な「メソッド的 if」について。
1.upto(20) do |n| (n % 15 == 0).if { puts 'FizzBuzz' }.else(n % 3 == 0).if { puts 'Fizz' }.else(n % 5 == 0).if { puts 'Buzz' }.else { puts n } end
(真偽値).if {...}
の形に合わせて else-if をメソッドチェーンの形に入れようとすると、上のような気持ちの悪い形にせざるを得なかった。この形は他にも問題があって、
}.else (n % 3 == 0).if {
と空白文字を入れると構文解析が変わってエラーになる。それなんて Perl?
それから、これは今まで挙げた全ての実装に当てはまることだが、else-if の条件式の扱いが実は正しくない。どこかの if/else-if の条件式が真になって対応する記述が実行されたら、その後にある else-if の条件式は評価されないはずである。
よく考えてみれば、「if メソッド」でなくて「then メソッド」ということにすればよい。
1.upto(20) do |n| (n % 15 == 0).then { puts 'FizzBuzz' }.elsif { n % 3 == 0 }.then { puts 'Fizz' }.elsif { n % 5 == 0 }.then { puts 'Buzz' }.else { puts n } end
……ということを、偶然見かけた「ドリトル入門」のページ*1を読んで思いついた。
もはや「if 関数」を実装するという元ネタからは随分離れてしまっているので、これの実装は措いておきたい。というか、折角実装するのであれば、普通の if 文よりも高い機能を持たせるべきであろう……。
(続く)
*1:そこの 6.3 節の条件分岐の内部動作の解説。