Rubyでリスト構造

id:muscovyduckさんのリスト構造の要素から、条件を満たす要素を取り出す - バリケンのRuby日記 - Rubyistのコードをリファクタリングしてみました。参考まで。

class List
  include Enumerable

  def initialize(car = nil, cdr = nil)
    @car = car
    @cdr = cdr
  end
  attr_accessor :car, :cdr

  def add_last(x)
    a = self
    a = a.cdr until a.cdr.nil?
    a.cdr = List.new(x)
  end

  def size
    inject(0) {|n, a| n += 1 }
  end

  def each
    a = self
    begin
      yield(a.car)
    end while a = a.cdr
  end
end

if __FILE__ == $0
  z = List.new('Ruby')
  z.add_last('Haskell')
  z.add_last('Java')
  z.add_last('Perl')
  z.add_last('Python')
  
  puts z.size # => 5
  z.each {|i| puts i }
  # => Ruby
  #    Haskell
  #    Java
  #    Perl
  #    Python
  
  z = List.new(1)
  z.add_last(2)
  z.add_last(3)
  z.add_last(4)
  z.add_last(5)
  z.add_last(6)
  
  p(z.find_all {|a| a % 2 == 0 }.to_a)
  # => [2, 4, 6]

  p(z.find_all {|b| b % 3 == 0 }.to_a)
  # => [3, 6]
end

主な変更点。

  • Enumerableをincludeしておきました。eachさえ定義しておけばいろんなメソッドが使えるようになります。find_allもこれで使えるようになります。
  • carとcdrの使い方が慣例と逆のような気がするので慣例に合わせました。
  • 先頭のダミーのListオブジェクトをなくしました。