JavaScript
switch

switch(true) が嫌な理由、説明しにくい

More than 3 years have passed since last update.


うおー!

switch(true) イディオム考察」とゆー記事を読んだ。とりあえず、心の中で即答した上で、「うおー説明しにくい!」ってなったので書いておく。「switch(true)って何?」という向きは、リンク先をご覧あれ。


論理値の比較はやめておけ

私が心の中で即答したのは、「論理値の比較はやめておけ」ということだ。論理値の比較は、そして特にリテラルとの比較はやめておけ、ということだ。つまり、下記みたいなもん全部だ。

// 1

if(true === bJudge){}

// 2
if(bFlag === (c===d)){}

// 3
if((a===b)===(c===d)){}

// 4
switch(true){
case a < 0:
break;
case b > c:
break;
}

// 5
switch(a > b)
case c > d:
break;
default:
break;
}

でもね。「これって、何で?」という純真でおめめキラキラな問いには、答えられそうで根拠が足りない。1なんかは、無意味だからやめれ、とよく言うけど、1回のムダは理由次第で許される場合もある。例えば、あまり自明でない演算子の優先順位を強調するために、言語仕様上は無意味な「念のためカッコ」を付けるのは、可読性の上から許されるだろう。では、なぜコレがいけないのか。うまく答えられない。2なんかは、場合によっては本質だったりする。bFlagがconfigで設定された値で、条件を反転させる機能がある場合だ。でも、心の中でやめれと叫ぶ声がする。3と5はまあ、分かりにくいよね。これは説明の必要は無いだろう。多くの人とは合意できそうな気がする。何となれば、多数決でも良さそうだ。こう書ける場面に遭遇したことはあるけれど、まあ書かん方が良い。

では、4。やめて欲しいけど、やっぱり「なぜ」をうまく主張できない。可読性の話は、多数決で圧勝できそうな時くらいしか主張できない。それなりにたくさんの実例が存在してしまうと、「要は慣れればOK」という主張に反駁できる何かが必要になってしまう。論理的な段階の数とか、依拠する数学的なモデルとか、そういうところに帰着できないと、なかなかうまく主張できた気がしないのだ。


ループは事情が違うよ

なお、上の例にループが一切無いけど、ループ条件にtrueを入れるのは、真偽値の比較をしているわけではなく、単に評価させているだけなので別に違和感を感じない。特に、while(true)なんかにはキモさは感じない。あくまで「感じない」というだけで、これも明確に説明できるわけじゃないんだけどね。

不思議なもんだね。

でも、感覚的ないやーんって、突き詰めると単なる感情であることが判る時もあるし、無意識ではあるけど真っ当な理由が存在する時もある。だから、考える価値はあると思うんだ。どっちなのか未だわからないので、もう少し考えたい。


フォールスルーの問題はまた別なんじゃないかな

switchが「ラベル」を選択するのか「ブロック」を選択するのかが言語によって無茶苦茶ぶれるんだよね。そして、直感的に「ブロック」を選択するように感じやすい。ツールによるフォールスルーの表示の仕方も、「ブロック」として認識している表れだ。やっぱり選んでいるのは「ラベル」だとはわかりにくいんだよ。そして、ブロックとして認識していると、各ブロックの順序は交換可能だと錯覚しかねない。まあ、それは避けられたとしても、フォールスルー先のロジックを修正した時、フォールスルーによって到達するパスに対する望ましくない影響を過小評価しがちだ。フォールスルーだと判っていてもね。

あとさ、「ラベル」を選択しているということは、コレってGOTOなんだぜ?