良いかき方がわからない

整数の配列がある。

  • 順番にアクセスしていって、データが3の倍数なら新しいランダムな整数で更新する。
  • またそのときは、次のデータをデクリメントして読み飛ばす。

[3,2,5,9,7,1,3,9,4,2,1,5,7,1,0,5,5]が、
[7,1,5,5,6,1,7,8,4,2,1,5,7,1,8,4,5]

C++とかだと普通に書ける。

  for (int i=0; i<SIZE(data); i++) {
    cout << setw(4) << right << data[i];
    if (data[i]%3 == 0) {
      data[i] = RAND();
      if (i+1 < SIZE(data)) {
        data[i+1]--;
      }
      i++;
      cout << setw(4) << "";
    }
  }
  cout << endl;

SIZEとかRANDとかは適当にマクロででも。
Rubyだと同じようにして

# (A)
i = 0
while i < data.size
  print "#{data[i]}  "
  if data[i]%3 == 0
    data[i] = rand(100)
    data[i+1] -= 1 if data[i+1]
    i += 1
  end
  i += 1
end
puts

とか、

# (B)
a = (0...data.size).to_a
for i in a
  print "#{data[i]}  "
  if data[i]%3 == 0
    data[i] = rand(100)
    data[i+1] -= 1 if data[i+1]
    a.shift
  end
end
puts

とか。
(A)は、ループ変数が外にあってうれしくない。
(B)は、ループ変数と、aみたいな配列を使っててうれしくない。a.shiftもちょっとトリッキー。
RubyでもC++みたいに、むだな外部変数無しに、すっきりと書くにはどうすればいいんだろう。
each系でやるのは、「次の要素」へのアクセスができないので外部で宣言したフラグがいりそうだし。

外部イテレータとか内部イテレータの違いって、こういう所?外部イテレータの有利な場面なのかな。

[追記(2007/06/14)]
あまり読まずに未来へトラックバック

自分は何も書いてないけど、コメントでhs9587さんが書いてくれてます。内部イテレータだとやりにくいよね、という話でいいのかな?

いま見ている要素の前後を触りたいとか、最初から何番目なのかでやることを変えたいとかは、それ用のメソッドがもう少しあっても(あった方が)いいですね、ということをrubykaigi2007懇親会でhs9587さんと立ち話しました。