きりのちはれ

やみときどきひかり

おもうがままに。

for文を書くともやもやするという話

たまには技術者的な話題を。

N = 10;
for(i = 0; i < N;  i++)
{
   //do something
}

説明するまでもないことですが、for文とは「処理をN回繰り返す」構文です。

プログラムを書いたことがある人で、この構文を書いたことない人というのは多くないのではないでしょうか。

皆さんはfor文はお好きですか? 私は最近、for文を書くことに抵抗感を覚えます。

あまり上手くお伝えできる気がしないのですが、自分なりにfor文への違和感を言語化してみたいと思います。

ちなみに私はどちらかというとオブジェクト指向*1派な人間だと思います。

なのでおそらく、「オブジェクト指向的な観点」で語られることをご承知下さい。

for文は何のために書かれるか

for文を利用する時、私達は一体なにをしようとしているのでしょうか?

  • コレクションの要素に対する処理
for(i=0; i < count(items); i++)
{
  hoge(items[i]);
}

要素の集まりをなめる、いわゆるイテレーションですね。

実際にこのような実装をする場面がどれだけあるのかは存じかねますが、

for文による実装の典型例の一つかと思います。

ここで、要素数count(items)は、items自身に関する情報です。

「itemsのみによって知る情報を元に1,itemsに処理を適用している」と読めます。

すなわち成したいことは「コレクション自身に対する処理」です。

自分自身に対する処理で、その情報を外に取り出して判断を委ねるべきでは無いと思います。

  • N個の要素に対する処理, N回の処理(ストレッチ)
N = someNumber;
for(i=0;i<N;i++)
{
  fuga(items[i]);
}
N = someNumber;

for(i=0;i<N;i++)
{
  stretch();
}

このようなfor文の利用はそこそこ多いのではないかと思います。

  • たくさんある要素から"幾つか"を選択して処理をしたい。
  • "何度か" 処理を重ねがけしたい。

自分自身まだ整理しきれていない部分ですが、このような要求が発生すると自然に

たくさんある要素処理 の方に注目してしまいがちだと思います。

  • 「沢山のデータを集めてきて、そのうちの幾つかを取り出したい」
  • 「ハッシュ化処理を1000回重ねがけする」

"沢山のデータ"や"ハッシュ化処理"が文脈の主役に見えるのでは無いでしょうか。

このような状況をオレオレワードで"主役の入れ替わり"ガンダムSEED Destinyと呼んでいます。

すなわち、ここで真に注目すべきは "幾つか" "1000回" の方では無いかと思うわけです。

幾つか選ぶということは「幾つか選びたい」原因がどこかにいるはずです。

これはコード上の「constで宣言」とか「どこそこのオブジェクトから渡ってきた値が」

という話ではなく、もっと抽象的な、顧客が本当に欲しかったものレベルの話です。

「100個中3個を処理する」のであれば、 3個を要求する何か がいるはずです。

somethingが要求するもの/用意する枠が3つあり、

その各枠に対するイテレーションの結果3つの値が残る…と考えるべきでないでしょうか。

同様に「1000回hashする」時、hashを1000回やるのではなく、

何らかの要求に基づいた 1000回というモノ が居て、自分自身の各回に基いてhashを呼ぶ…

と考えられないでしょうか*2

何が言いたかったか

繰り返しになりますがfor文は「何回か」処理を行う構文です。

では「何回か」とはなんでしょうか。

こいつの正体に向き合うことは、その裏側にいる要求を見ることに他ならず、

「何回か」を根拠に基づいた「モノ」に落としこめるのでは無いでしょうか。

そして「何回か」が無くなるのであれば、

必然的にfor文を書く場面は無くなっていくような気がしています。

この辺を突き詰めていくと、手続き指向とかオブジェクト指向とか関数型とか

そういう概念の本質の一端に触れられそうな気がするんだよなぁ。

小さな話題だけど色々な方の知見に触れて考えを深めてみたいものです。。

むにゃり。

*1:この言葉もふわふわとして良くないと思うが

*2:うろ覚えだが確かrubyには Int.times のようなものがあり、まさしくこういう概念だと思う