ごとけんです

In message "[ruby-list:19246] 破壊的イテレータ?"
    on 99/12/08, Hiroshi Saito <HiroshiSaito / pob.org> writes:
>a.itr do |i|
>    i += 10
>    print i, ","
>end

i += 10 は i = i+10 なので、i という変数が何を指すかを変えて
いることになります。絵で描くと以下のような感じ:

ブロックの実行を始めたところ:

   a = [1, 2, 3, 4, 5]
        ↑
        i

i += 10 を実行した後:

   a = [1, 2, 3, 4, 5]

        i→11

>つまり、イテレータのブロックでの結果をイテレータ本体に
>持ち越すことはできますか?

Rubyの変数はオブジェクトを指すだけのもので、変数に対する操作
は代入(指すものを変えること)と参照しかないので、
  (1) 添字を使ったイテレータにして、添字で指定したコンテナの
      位置に代入させるか
  (2) 参照しているオブジェクトを変化させる方法をつかうか

のいずれかできます。

# (1) の例
  h = {:foo => 0, :bar => 1, :baz => 2}
  h.each_key{|key|
    h[key] += 10  # Hash#[]= の呼出し
  }
  p [h[:foo], h[:bar], h[:baz]]  #=> [10, 11, 12]

  a = [0,1,2]
  a.each_with_index{|e,i|
    a[i] = e + 10  # Array#[]= の呼出し
  }
  p a  #=> [10, 11, 12]

# (2) の例
  a = [[0],[1],[2]]
  a.each{|i| 
    i[0] += 10  # 各要素iへの Array#[]= の呼出し
  }
  p a  #=> [[10], [11], [12]]

また Array#filter は評価した結果で要素を置き換えるものです。

  a = [0,1,2]
  a.filter{|i| i+10}
  p a  #=> [10, 11, 12]


ユーザ定義する場合はこれらのいずれかを用意する必要があります。

-- gotoken