バリケンのRuby日記 RSSフィード

2006-06-03

[] Rubyリスト構造の実装  Rubyでリスト構造の実装 - バリケンのRuby日記 を含むブックマーク はてなブックマーク -  Rubyでリスト構造の実装 - バリケンのRuby日記  Rubyでリスト構造の実装 - バリケンのRuby日記 のブックマークコメント

ようやく「ふつうのHaskellプログラミング」を買うことができたよ。

ただ、HaskellHaskell以外のプログラミング言語を比較するとき、サンプルコードがJavaで書かれているみたいだよ。なので、せっかくだからサンプルコードをRuby移植してみることにするよ。

まずは5ページ目のサンプルコードをRuby移植してみるよ。ここでは「あるリスト構造に含まれる要素のうち、条件を満たす要素だけで新たにリストを生成する」というメソッドがサンプルとして掲載されているよ。

そのまえに、Rubyリスト構造を実装しないとダメだよね。リスト構造を実装するには「値」と「次の要素へのラベル」を要素として持つオブジェクトがあればよさそうだから、次のようにListクラスを定義すればいいかな。

class List
  def initialize
    @cdr = nil
    @car = nil
  end
end

ここで、@cdrは「値」、@carは「次の要素へのラベル」を表すインスタンス変数とするよ。

このままだと値が設定できないよね。じゃあ、アクセサを追加しよう。

class List
  def initialize
    @cdr = nil
    @car = nil
  end
  attr_accessor :cdr, :car
end

これで、値が追加できるようになったね。でもこのままだとリストに要素を追加するのが面倒だから、リストの最後に要素を追加するadd_lastメソッドも定義してみるよ。

class List
  def initialize
    @cdr = nil
    @car = nil
  end
  attr_accessor :cdr, :car

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

リストのサイズも知りたくなるよね。ということで、リストの要素を数えるsizeメソッドも追加してみたよ。

class List
  def initialize
    @cdr = nil
    @car = nil
  end
  attr_accessor :cdr, :car

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

  def size
    a = self
    i = 0
    i += 1 while a = a.car
    return i
  end
end

リストの各要素に対して繰り返し処理をするイテレータが欲しいよね。ということで、ブロックを与えるとリストの各要素に繰り返し処理をするeachメソッドも追加してみたよ。

class List
  def initialize
    @cdr = nil
    @car = nil
  end
  attr_accessor :cdr, :car

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

  def size
    a = self
    i = 0
    i += 1 while a = a.car
    return i
  end

  def each
    a = self.car
    self.size.times do
      yield a.cdr
      a = a.car
    end
  end
end

じゃあ、このへんでオブジェクトを生成してうまく動くか試してみよう!

class List
  def initialize
    @cdr = nil
    @car = nil
  end
  attr_accessor :cdr, :car

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

  def size
    a = self
    i = 0
    i += 1 while a = a.car
    return i
  end

  def each
    a = self.car
    self.size.times do
      yield a.cdr
      a = a.car
    end
  end
end

z = List.new
z.add_last('Ruby')
z.add_last('Haskell')
z.add_last('Java')
z.add_last('Perl')
z.add_last('Python')

puts z.size

z.each do |i|
  puts i
end

実行結果だよ。

5
Ruby
Haskell
Java
Perl
Python

まだまだ追加したいメソッドはいっぱいあるけど、とりあえず今日はここまで。

トラックバック - http://rubyist.g.hatena.ne.jp/muscovyduck/20060603