JavaScript
関数型プログラミング

なぜfor文は禁止なのか?関数型記述のススメ


なぜfor文は禁止なのか。

結論からいうと、可読性のためです。

for文は何かを「繰り返し処理をする」ことに使いますが、実際に求められるのは、「全ての要素に処理をする」とか、「母集団から選択して処理をする」こともおおくあります。

また、for文を用いることは、関数名にfuncという名前をつけるのと似ています。こんな関数名あっても、何をしてくれる関数かわからないだろう。と。

for文も同じで、繰り返すやるのはわかるが、何故繰り返すのか、どの要素に対して何をやるのかわからないだろう、だから禁止だ。ということです。異論は認めます。

これ以上の言語化が難しいので、サンプルコードを例示します。


サンプルコード

サンプルの命題は、

0から100未満の偶数のみを累計する。

とします。


禁止

var totalOfEvenNumberUnder100 = 0;

for (var i = 0; i < 100; i++) {
if (i % 2 === 0) {
totalOfEvenNumberUnder100 += i;
}
}

命題に、「繰り返す」という文字がないのに、forで繰り返しています。手続き型に慣れたプログラマは、もう違和感を感じなくなってしまっているかもしれませんが、なぜ繰り返すのでしょうか。0から100未満の数字がほしいだけなのに。

また、最初に0で変数を初期化するのも命題にはありません。

さらには、偶数のみを取り出す処理と足す処理が交互に行われることになっています。偶数のみを累計する、という命題とは違う処理になってしまっています。

もちろん答えは一緒ですが、命題とは別の処理になってしまっているともいえます。


推奨

できるだけ処理に名前をつけていきます。

命題を「0から100未満」と、「偶数のみ」という処理と、「累計する」という処理に分解して名前をつけます。

const from0To100Array = Array.from(Array(100).keys());

const isEvenNumber = i => i % 2 === 0;
const addAll = (total, i) => total + i;
const totalOfEvenNumberUnder100 = from0To100Array.filter(isEvenNumber).reduce(addAll);

「0から100未満」がfrom0To100Array

「偶数のみ」がisEvenNumber

「累計する」がaddAllです。

最後に「0から100未満」から「偶数のみ」を取り出して「累計する」をしています。

この方が命題に即しているのではないでしょうか?

今回は、関数型に有利な命題を選択したような気もするのですが、実際にプログラムに求められる処理には、このような形式の命題も多くあります。

for文のような手続き型だけでなく、関数型でも処理を記述できるエンジニアになってみるのも良いと思います。

(あれ?for文禁止から随分トーンダウンしたじゃないか、というご指摘ですか?ですよね。。。実際for文を書いたほうが、短くプログラミングできることもありますからね。。。。失敬)

現場からは以上です。