6月の雨の日,僕は古いアルバムのジャケットを眺めていた。曲名をなぞるだけで,彼らの音楽が頭に入り込んでくる。僕はこのアルバムを何度も何度も聞いた。小さな女の子がダイヤモンドでかっ飛んで,戦争の映画を見て,どこかの寂しいバンドがライブハウスで歓声を浴びている。そんなアルバムだ。

 そのアルバムは,名盤であるとうたわれていた。もちろんそれは今も変わらない。評論家いわく,雑多な音楽の集合体であるアルバムに,「物語というコンテキストを持ち込んだ」と。確かにいくつかの物事が一つの軸によって結び付けられていることは,それだけで美しいと感じる。

 僕はRubyを書いているときにも同様の感覚を持つ。Rubyは,何かしらのRubyっぽさ,つまりRubyの軸があり,その空気ともいうべき軸がRubyらしさを支えている。それが何かを明確に言い当てることは,非常に難しいとしてもだ。

 前回は,イテレータについて少し解説した。基礎的なことを説明しただけだから,イテレータの魅力が伝わりにくかったかもしれない。今回は,もう少しイテレータを深くみていくとともに,頻繁に使用する配列操作に便利なメソッドも紹介しよう。

 今回も懲りずにツールを作ろう*1。頼んできたのはもちろん,僕の大学時代からの友人Kだ。作るツールは,「映画について書いたラブレターの一覧作成ツール」である。友人Kは,女の子と映画をよく見に行くようなのだが,誰とどの映画をいつ見たかをはっきり覚えていないらしい。そこで映画を話題にしたラブレターの一覧が必要になったのだとか。

 やれやれ,恋人以外の女性と映画に行くのはまだよいとしても,その女性に手紙を書いて,しかもそれを「ラブレター」なんて呼ぶあたりに,友人Kの人格が象徴されている。

イテレータの復習

 少しだけ前回のおさらいをしておこう。イテレータは繰り返し処理の機能で,配列などでよく使用される。イテレータを用いたコードは,例えばリスト1のようになる。

array = ["John" , "Paul" , "George" , "Ringo"] ----(1)
array.each do |name| ------------------------------(2)
  puts name ---------------------------------------(3)
end
リスト1●イテレータの例

 リスト1の(1)で,4人の名前を格納した配列を生成している。(2)のeachメソッドを用いて配列の要素一つひとつにアクセスし,各要素をnameという変数に格納する。(3)の「puts name」において,要素である名前を表示する。イテレータの使用はたったこれだけだ。難しくはないだろう。

 それでは,イテレータを使うといったい何が嬉しいのだろうか。それを解き明かす手掛かりとして,Javaで同じような処理を記述してみよう。

 Java*2で記述するとリスト2のようになる。リスト2の(1)でRubyと同じように配列を生成している。型宣言が必要なのは,Javaにおいては仕方のないことだ。ここでのポイントは,(2)と(3)だ。

String[] array = {"John" , "Paul" , "George" , "Ringo"}; --(1)
for(int i=0; i < array.length; i++) { ---------------------(2)
  String name = array[i]; ---------------------------------(3)
  System.out.println(name);
}
リスト2●Javaでイテレータを記述したプログラム

 Javaでは繰り返し処理のためにfor文を使用する。(2)のfor文を使用している中で「int i」という制御変数iを宣言している。これが一つ目のポイントだ。

 制御変数iは,繰り返し処理が何番目の配列要素を参照するのか,といった制御に使用される。一見すると重要そうな変数だが,リスト1の処理は配列を先頭から順にアクセスしていくだけだ。単なる順次アクセスに,この制御変数iは本当に必要だろうか?

 もし,先頭から順にアクセスすることだけを考えるのであれば,制御変数なんて必要ないと言える。順番に参照すればよいため,それが何番目に存在するのかは大した問題ではないのだ。

 また,配列を利用するプログラムでは,先頭から順番に要素を処理していくことが多い。ときとして一つ飛ばしで配列要素にアクセスしたり,先頭要素だけ処理したくないといったこともあるのだが,多いのは「先頭から最後まで一つずつ配列の要素に対して処理していく」という方式だ。僕もJavaで,for文を使い先頭から順にアクセスするためによく使用した。「for(int i=0; i<array.length; i++)」というコードを,壊れて止まらない扇風機のように何千回書いたかわからない。

 制御変数は,「配列の先頭から順番に一つずつ処理する」という場合には,本質的な変数ではないということになる。