Mae向きなブログ

Mae向きな情報発信を続けていきたいと思います。

Arrayにtailsメソッドを追加する方法

あんまり面白くない例ですが,

[1, 2, 3].tails

を実行したときに,以下のような結果を返すtailsメソッドを追加する方法を考えます。

[[1, 2, 3], [2, 3], [3]]

クラスを再オープンする方法

class Array
  def tails
    ary = []
    self.each_with_index do |ele, idx|
      ary << self[idx, self.length]
    end
    ary
  end
end

p [1, 2, 3].tails   #=> [[1, 2, 3], [2, 3], [3]]

特異メソッドを利用する方法

この方法だと,aryだけにしかtailsメソッドは追加されません。

ary = [1, 2, 3]
def ary.tails                   
  ary = []
  self.each_with_index do |ele, idx|
    ary << self[idx, self.length]
  end
  ary
end

p ary.tails   #=> [[1, 2, 3], [2, 3], [3]]

Mix-inを用いる方法

module Tails
  def tails
    ary = []
    self.each_with_index do |ele, idx|
      ary << self[idx, self.length]
    end
    ary
  end
end

class Array
  include Tails
end

p [1, 2, 3].tails   #=> [[1, 2, 3], [2, 3], [3]]

次に,Mix-inを使って,以下のようにArrayでもStringでもtailsメソッドが使えるようにしてみます。マルチバイト文字のことは考慮してません。

[1, 2, 3].tails #=> [[1, 2, 3], [2, 3], [3]]
"abc".tails     #=> ["abc", "bc", "c"]

each_with_indexは,Stringのインスタンスメソッドに含まれないので使えません。each_byteメソッドが使えそうですが,これはArrayのインスタンスメソッドに含まれません。ということで,whileを使って作ってみました。

module Tails
  def tails
    ary = []
    idx = 0
    len = self.length
    while idx < len
      ary << self[idx, len - idx]
      idx += 1
    end
    ary
  end
end

class Array
  include Tails
end

p [1, 2, 3].tails   #=> [[1, 2, 3], [2, 3], [3]]

class String
  include Tails
end

p "abc".tails       #=> ["abc", "bc", "c"]