再帰的にeach

再帰的にArrayを反復するようなものを書いて見ました。 

#!/usr/bin/env ruby

class Object
  class Array
    def reflexive_each(&p)
      self.each do |arr|
        if arr.class == Array
          arr.reflexive_each(&p)
        else
          p.call(arr)
        end
      end
    end

    def reflexive_map(&p)
      self.map do |arr|
        if arr.class == Array
          arr.reflexive_map(&p)
        else
          p.call(arr)
        end
      end
    end

    def reflexive_map!(&p)
      self.map! do |arr|
        if arr.class == Array
          arr.reflexive_map!(&p)
        else
          arr = p.call(arr)
        end
      end
    end
  end
end

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

array.reflexive_each {|arr| p arr + 1 }
#=> 2
#=> 3
#=> 4
#=> 5
#=> 6

p array.reflexive_map {|arr| arr + 1 }
#=> [2, 3, 4, [5, 6]]
p array
#=> [1, 2, 3, [4, 5]]

array.reflexive_map! {|arr| arr + 1 }
p array
#=> [2, 3, 4, [5, 6]]

 意外と便利そうです。1つ欠点があるとすると。

p array.map {|arr| arr.class }
#=> [Fixnum, Fixnum, Fixnum, Array]
p array.reflexive_map {|arr| arr.class }
#=> [Fixnum, Fixnum, Fixnum, [Fixnum, Fixnum]]

 と言うことで、Arrayは無視されるようになりました。Class別になにか操作させたいときに、Arrayが使えなくなってる訳です。Array以外でブロックを呼び出すようにしてるので当然と言えば当然ですかね。
 String#scanとか使うと配列が入れ子になる場合があるので、これを使うと便利かも知れません。