他のプログラム言語のif構文の中で使われるelse ifをRubyで使う場合、elsifが用いられます。これは、「ぶら下がりelse問題」によるもので、Rubyの特徴の1つです。ただし、Rubyではelsifが使えるから大丈夫、ということではありません。
今回は、else ifによる「ぶら下がりelse問題」と、Rubyにおけるif構文を使う際の注意点について解説します。
Rubyのぶら下がりelse問題
「ぶら下がりelse問題」をご存じでしょうか。C言語やJavaなどのプログラミング言語を学んだ方は、if構文を{}で囲うので、入れ子になったif文が記述できます。しかし、Rubyには{}が無いので、2つ目以降の条件か、それとも、入れ子の条件かを明確に区別しなければなりません。
そのため、Rubyのif構文は、C言語やJavaなどの他のプログラム言語のif構文と違っています。まずは、Rubyにも関係が深い、ぶら下がりelse問題について説明します。
入れ子のelse ifとは
例えば、下記のC言語のif構文を見てください。条件1のelse構文の中に、さらにif構文を記述しています。C言語は、if構文を{}の中に記述しているので、入れ子のif文の構文は、明確に区別されます。
C言語のif構文
if( 条件1 ) { 処理1; } else if( 条件2 ) { 処理2: }else { if( 条件3-1 ) { 処理3-1; } else { 処理3-2; } }
この処理をrubyで記述する場合、C言語のような{}が無いので次のように記述します。
Rubyのif構文
if 条件1 then 処理1 elsif 条件2 then 処理2 else if 条件3 then 処理3-1 else 処理3-2 end end
もし、C言語の「else if (条件2)」をrubyでも書けたら、どうなるでしょうか。入れ子でない「else if 条件2」と、入れ子の「else if 条件3」が同じ書き方になってしまい、Rubyのプログラムは入れ子の判断ができません。
これは、Rubyにおける「ぶら下がりelse問題」、または、「ダングリングelse」と呼ばれています。
Rubyにはelsifとelse ifがある
先ほど説明したように、Rubyのif構文では、「ぶら下がりelse問題」があるので、複数の条件を使ってif構文を使う場合は、elsifを使用します。
elsifの構文
if 条件1 then 処理1 elsif 条件2 then 処理2 else 処理3 end
また、if構文が入れ子になっている場合は、else ifが使われているように見えます。
入れ子のif構文
if 条件1 then 処理1 else if 条件2-1 then 処理2-1 else 処理2-2 end end
「ぶら下がりelse問題」は他の言語でも
Rubyの特徴は、記述量が少なく、ソースコードの可読性に優れ、保守性の高いプログラムを作れることです。しかし、ぶら下がりelse問題のように、記述量が少ないせいで問題になることもあります。
では、他のプログラム言語でも、「ぶら下がりelse問題」があるのでしょうか。例えば{}で囲うのでC言語やJava、PHPではもちろんありません。さらに、字下げするPythonでも無関係です。
しかし、PHPやVisual Basicではelseifを使います。また、PerlでもRubyと同じelsifが使えるます。このように「ぶら下がりelse問題」でRubyだけでの問題ではありません。
Rubyではifでelseとelsifが使える
先ほど解説したように、Rubyには「ぶら下がりelse問題」があり、if構文でelseとelsifを使い分けます。そして、その違いを確認できる例が次のとおりです。
2つ目以降の条件はelsif
Rubyのif構文で、2つ目以降の条件を設定する場合は、elsifを使います。
if構文の文法
if 条件1 then 処理1 elsif 条件2 処理2 end
if構文の例
chk=1 if age = 65 then chk=3 end
上記の例は、変数ageの値が18より小さい場合、と、変数ageの値が65以上の場合で、別の処理を実行しています。そして、2つ目の条件に、elsifを使います。
条件に該当しない場合はelseで
Rubyのif構文で、条件に該当しないケースの処理を記述するは、elsifを使います。
if構文の文法
if 条件 then 処理1 else 処理2 end
if構文を使った例(入れ子なし)
if chk == 1 then checker = "OK" else checker = "NG" end
先ほど説明したように、Rubyのif構文を入れ子で記述できます。そのため、次のようなif構文も書けます。
if構文を使った例(入れ子あり)
if chk == 1 then checker = "OK" else if sw == 1 then checker = "NOTICE" else checker = "NG" end end
この例は、if構文のelseの下に、入れ子でif構文を記述した例です。
なお、下記のように1行で記述しても、正常に動作します。しかし、「else if」は他のプログラム言語と意味が違い、入れ子のif構文になっているので注意してください。
if chk==1 then checker="OK" else if sw==1 then checker="NOTICE" else checker = "NG" end end
Rubyのぶら下がりelse問題を回避するには
これまで紹介したように、C言語のelse ifに相当するRubyの構文はelsifです。そして、Rubyでもelse ifと書くことは可能ですが、それは、elseの下に入れ子でif構文を書いたケースで意味が違います。
紛らわしいelse ifの書き方を避ける方法を使うように心がけましょう。次から、Rubyのぶら下がりelse問題を回避する方法について説明します。
if修飾子で置き換える
Rubyでは、C言語やJavaよりも、短く読み易いプログラムを書ける点が特徴で、プログラムを簡潔に記述する方法が幾つもあります。もし、簡単なif構文であれば、if修飾子の記述を検討してください。なお、if修飾子とは、条件に一致する場合のみ、式を実行するための修飾子です。
if修飾子の文法
式 if 式
if修飾子を用いた例
if chk == 1 then checker = "OK" else checker = "NG" checker = "NOTICE" if sw == 1 end
これは、先ほどの入れ子のif構文を、if修飾子で書き換えた例です。入れ子のif構文が簡単な処理であれば、シンプルに記述できます。
条件演算子を活用する
Rubyには、先ほど紹介したif修飾子に似た機能として、三項演算子を使用できます。なお、条件演算子は三項演算子とも言いますが、変数に代入する際、条件に該当する場合の値と、該当しない場合の値を指定できる演算子です。
条件演算子の文法
条件 ? 該当する場合の値 : 該当しない場合の値
条件演算子は、下記のif文と同じ機能を提供します。
if 条件 then 該当する場合の値の代入 else 該当しない場合の値の代入 end
条件演算子の例
checker = sw == 1 ? "NOTICE" : "NG"
この例は、変数swの値をチェックし、もし1なら”NOTICE”を、1でなければ”NG”を、checkerに代入する条件演算子を使った式です。
そして、if構文に条件演算子を組み合わせると、先ほどの例を次のように記述できます。
条件演算子を用いた例
if chk == 1 then checker = "OK" else checker = sw == 1 ? "NOTICE" : "NG" end
メソッドに分ける
先ほど説明したように、Rubyの簡単なif構文は、if修飾子や条件演算子で置き換えることで、短く読み易いプログラムが書けます。しかし、入れ子のif構文が、このように簡単なif構文とは限りません。
もし、複雑なif構文の入れ子の構造を見直したいなら、メソッドに分ける方法を活用してください。
if構文をメソッドで分けた例
def ng_case(sw) if sw == 1 then return("NOTICE") else return("NG") end end if chk == 1 then checker = "OK" else checker = ng_case(sw) end
まとめ
これまで説明したように、Rubyのif構文には、elsifとelseがあり、使う場所が違います。そして、他のプログラム言語で使えるelse ifは、Rubyでは使えないので注意してください。
そして、Rubyでif構文を入れ子にすると、ぶら下がりelse問題に直面します。if構文の入れ子を使ったプログラムを避けてください。
Rubyでは、if修飾子や条件演算子を使えばif構文と同じように書けます。さらに、メソッドを分けると、より見やすく書けるので、これらをうまく活用してください。