thenブロックの中括弧の省略について


いま、2chの某スレでC/C++Javaのifのthenブロックで中括弧を省略したほうがいいのかどうかについての議論が繰り広げられていて、面白そうだったので取り上げてみる。*1


要は、次の書き方は中括弧を省略したほうがいいのか?

  if (xxx) { continue; }


という、昔からよくある議論である。



その前にまず言っておかなければならないが、「(文法的には)中括弧を省略できる」という表現は正しくないと私は思う。


と言うのも、C/C++Javaの文法的には、


1) statement : if ( expression ) statement1 [else statement2]
2) statement : { [ statement-list ] }
3) statement-list: statement または statement-list statement
※ [ ] は省略可能という意味。


という文法規則があって、1)を見てわかるように、ifのthenブロックに来るのは、statement(単文)である。それを3)と2)の規則を経て、わざわざ "{" "}"を付与しているわけであるから、文法構造的には「中括弧を省略」しているのではない。


もともと1)の規則からすれば、ifのthenブロックに"{" "}"は、不要なのに、あえて3)の規則(1つ以上の単文の連続を複文とみなす規則)と2)の規則(複文を単文扱いするための規則)を用いて付与してあるのだ。


だから、「thenブロックって単文のときは { }を省略できるんだよ」とか言うのは、文法的に見れば全く正しくない。上の文法構造をきちんと理解している人はそんな言い方はしないのではないかと私は思う。ifのthenブロックには本来、単文しか来れず、また、複文が { } を伴って単文になれるというだけの話なのだから。


ただし、「thenブロックって必ず { } をつけたほうが、あれとかこれとかの理由で好ましく、必ず { }は付けるものであって、それをつけないのは“省略”だろ?」と言われるのなら、それはわからないではない。


しかし「thenブロックって単文のときは { }を省略できるんだよ」というような書き方をしている人はいっぱい居て、例えば、次の記事なんかだと「(中括弧の)“省略”が許可されている」と書かれている。このような記事はググれば山のように出てきて、そのどれもこれも突っ込みどころ満載のおかしいことばかり書いてあって、それと言うのもCの基本的な文法構造すらきちんと理解できていないような人が書すっごく面白いので暇な人はググってみてね!


カッコをつけたコードはカッコわるいのか論争
http://el.jibun.atmarkit.co.jp/hidemi/2009/07/post-29fb.html



まあ、それはそれとして、この中括弧をつけたほうがいいのかどうかという問題は、有名どころではJoel氏のブログでも2005年の記事で言及されている*2が、それよりずっと以前から存在する問題である。


私が知る限り、25年以上前、Cが普及しはじめたころにはすでにそういう議論があって、その当時の結論は、「中括弧を入れておけ」だった。それは、コードをあとでthenブロックに追加したときに、意図通りにならないからだった。

  if (xxx)
    foo();
    bar(); // これを追加した。


確かにもっともらしい理由に思える。私もCを覚えてから、その教えを守り、しばらくはわざわざ次のように書いていた。

  if (xxx) {
    foo();
  }

しかし、そうは言っても、「foo(); の行にはインデントしてあるのに間違うかなぁ?」と思い、解像度の低いディスプレイ(当時640☓400ドットだとか…)でプログラムの行数が増えるのは嫌だったし、私はしばらく中括弧を書かないことにしたが、特にこれが原因でバグったことはなかった。たぶん、そのあとの20数年間、thenブロックでの中括弧を私はしばしば省略したが、それを省略したがためにそのあと1行追加してバグったという経験は私は一度もないと思う。


だから、中括弧がないとバグの原因になるというのは、私にはどうも納得できない。もしかして、中括弧がないとバグると言っているのは、プログラミング経験の浅い初心者プログラマではないか?あるいは、初心者プログラマに向けて「最初はそう書きましょうね」という話ではないのか?


まして、いまどきの統合環境なら何らかの警告を出してくれるかも知れないし、thenブロックでfooと入力しているときにif (xxx) の部分が bold(太字)になって、ここからここまでがブロックですよと知らせてくれるかも知れない。


また、オートインデントのような機能があれば、foo();の次の行にbar();を追加するときにインデントの位置がおかしいので気づくだろうし、あるいはadd-onのリファクタリングツールをインストールしてあれば、bar();を追加しようとしたときに 「"{ }"は無くても大丈夫か?」と尋ねてきてくれるかも知れない。


だから、いまどきの統合環境なら、中括弧を書かないとしても、後々、それがためにバグるとは到底思えないのだ。


そんなわけで、もういい加減、「thenブロックの { } を省略してはならない」というコーディングスタイルを現場で部下に強制するのはやめにしないかと思うわけだ。


また、いま議論の対象となっているのは thenブロックで continue; と書くときであって、そもそもこの後ろに何かstatementを追加すること自体考えられない。この直前にならもしかしたら追加するかも知れないが、直前なら、さすがにいくらなんでも気づくだろう。


あと、統合環境が使えるなら上に書いたように何も問題ないと私は思うのだが、JavaScriptのような標準的な統合環境が普及していないような言語の場合はまた事情が違うのかも知れない。テキストエディタでべた打ちしたらもしかしたらこういうのがバグの原因になるかも知れない。


そのへんを含めて考えると結局どうなんだろう?


また、そのスレでは別方面からの意見として、単文でも最初から中括弧を入れておかないと、thenブロックにコードを追加した場合、diffをとったときに追加された"{" "}"の行も出てきて目障りだというのがあった。


その件は、「なるほどなぁ」と私は思った。私自身、ソース差分は滅多に取らないし、またExamDiffというツール*3を使っているのでそのへんは気にもならないのだが、そういう意見もあるんだなぁと思った。



ともかく、「thenブロックの中括弧は省略しないほうが良い」というのは、昔からプログラミングのお作法として広く知られている内容なのだが、いま使っている開発環境や社内のチーム環境でそれが適切な教えなのかを、我々は再考したほうがいいのではなかろうか。

*1:そのスレに常駐している人が2chにありがちな、ちょっとアレな人のようなのでここからリンクは貼りません。& コメント欄にそのurlを書いたらそのコメント消します。また、そのスレには私は書きこんでおりません。

*2:http://www.joelonsoftware.com/articles/Wrong.html

*3:http://www.prestosoft.com/edp_examdiff.asp