LoginSignup
7
2

More than 5 years have passed since last update.

else if とは何か

Last updated at Posted at 2018-07-13

社内で、人のプルリクを眺めていたら、新人と2年目との、不思議なやりとりがあった。

元々、こんなコードがあった。

もともと
if (isHoge()) {
    foo = something_value;
} else {
    foo = another_value;
}

別の方法でもfooを指定できるように改造することになったため、新人は以下のようなコードを書いた。

新人くんのコード
if (isGuruguru()) {
    foo = guruguru_value;
} else {
    if (isHoge()) {
        foo = something_value;
    } else {
        foo = another_value;
    }
}

そこに、2年目くんから「元々の処理を変更しない方がいい。ネストを深くしない方がいい」という物言いがついて、コードはこのように変更された。

修正後コード
if (isHoge())) {
    foo = something_value;
} else {
    foo = another_value;
}
if (isGuruguru()) {
    foo = guruguru_value;
}

これはものすごくよくない。
今回のやりとりを知らずに、このソースを見た人は、isGuruguruの部分だけを追いたかったとしても、関係ないところ読まされる上に「なんか、fooを2回代入してるけど、これ意味あんのかなぁ?」という疑問を抱きながら生きることになる。そういった人生を他人に送らせるべきではない。

最初に新人が書いたコードだが、gitのdiffで見ると、とてつもなく複雑な変更を加えているように見える。

gitのdiff
-if (isHoge()) {
-    foo = something_value;
+if (isGuruguru()) {
+    foo = guruguru_value;
 } else {
-    foo = another_value;
+    if (isHoge()) {
+        foo = something_value;
+    } else {
+        foo = another_value;
+    }
 }

けれど、よくよく見ると、これは新たにif else構文を1個付け加えて、元あったコードをelse節にぶちこんでるだけだ。
これは git diff -w のように、-w オプションを付けてdiffを取ると分かりやすい。

wオプションを付けてdiff
+if (isGuruguru()) {
+    foo = guruguru_value;
+} else {
     if (isHoge()) {
         foo = something_value;
     } else {
         foo = another_value;
     }
+}

ところで、C言語の規格書にはelse if構文はない、という話を聞いたことがあるだろうか。
http://kikakurui.com/x3/X3010-2003-01.html より、規格を引用する。

6.8.4 選択文
構文規則
     選択文:
        if ( 式 )  文
         if ( 式 )  文  else  文
         switch  ( 式 )  文
意味規則 選択文は,制御式の値に応じて幾つかの文の中から一つを選択する。
選択文はブロックとする。そのブロックの有効範囲は,それを囲むブロックの有効範囲の真部分集合とする。各副文もブロックとする。そのブロックの有効範囲は,選択文の有効範囲の真部分集合とする。
6.8.4.1 if 文
制約 if 文の制御式は,スカラ型をもたなければならない。
意味規則 両形式とも,式の値が 0 と比較して等しくない場合,最初の副文を実行する。else 形式の場合,式の値が 0 と比較して等しいならば,2 番目の副文を実行する。ラベルを通して最初の副文に制御が到達した場合,2 番目の副文は実行しない。
 elseは,構文規則で許される if のうち,その else の前で最も近い位置にある if と結び付く。
6.8.4.2 switch 文
...

見て分かる通り、else ifという構文はない。では、C言語でelse ifを書くとコンパイルエラーになるのか。いいや、ならない。
C言語においてはelse ifとは、if (式) 文 else 文 の、二つ目の「文」に、別のif文を持ってきているものとみなされる。
文は {}で囲うことができるので、例えば

else-if
if (式) 文
else if (式) 文
else 文

は、こう書くこともできる。

else-ifはこういう意味
if (式) 文
else {
    if (式) 文
    else 文
}

つまり、この2つの書き方は等価なのだ。

これはあくまでC言語の話で、例えばPythonなどでは、

Python_書けない例
if 式:
    文
else: if 式:
    文

のような書き方はできず elif といったキーワードが必要になるが、elseの中にif文だけを書くのと、if...elif...else構文を使うのが等価であることには変わらない。

elseのネストで書く
if 式:
    文
else:
    if 式:
        文
    else:
        文
elifを使った、上と等価なコード
if 式:
    文
elif 式:
    文
else:
    文

elifを使った方が断然見やすい。

ところで、話を元に戻そう。
新人が書いたコードを見てほしい。

再掲・新人くんのコード
if (isGuruguru()) {
    foo = guruguru_value;
} else {
    if (isHoge()) {
        foo = something_value;
    } else {
        foo = another_value;
    }
}

あ、else の中に if文が入ってる!
なので、これはこのように書ける。

else-ifで書き直した
if (isGuruguru()) {
    foo = guruguru_value;
} else if (isHoge()) {
    foo = something_value;
} else {
    foo = another_value;
}
7
2
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
2