Rubyの<=>演算子とComparableモジュールの関係
タグ: ruby / 初版公開: 2014-03-09

Rubyにおける<=>演算子は、基本的な比較演算子で、以下のことが期待されている。

self <=> otherは

  • self が other より大きいなら正の整数
  • self と other が等しいなら 0
  • self が other より小さいなら負の整数
  • self と other が比較できない場合は nil

試しにいくつか結果を見てみよう。 確かにInteger同士の<=>演算子による比較は、期待どおりの結果を返している。 また比較ができないIntegerStringの比較はnilを返すこともわかる。

1 <=> 0 #=> 1
1 <=> 1 #=> 0
0 <=> 1 #=> -1
0 <=> "" #=> nil

<=>演算子はsortメソッドのブロック内で利用できる。 以下は整数のリストをソートする、とてもつまらない例だ。

[3, 2, 1].sort{|v0, v1|
  v0 <=> v1
}
#=> [1, 2, 3]

正しく<=>演算子が定義されていれば、<=>演算子を使って、他の比較演算子を導くことができる。 その実装がComparableモジュールだ。 Comparableモジュールは以下のメソッドを<=>演算子を使って実装する。

  • <
  • <=
  • ==
  • >
  • >=
  • between?

試しに値を1つ保持するValueクラスに<=>演算子を定義して、Comparableモジュールをincludeしてみる。 すると確かに各種の比較演算子が使えるようになることがわかる。

class Value
  include Comparable
  attr_accessor :value

  def initialize(value)
    @value = value
  end

  def <=>(other)
    @value - other.value
  end
end

v1 = Value.new(1)
v2 = Value.new(2)
v3 = Value.new(3)

p v1 < v2 #=> true
p v1 <= v2 #=> true
p v1 == v2 #=> false
p v1 > v2 #=> false
p v1 >= v2 #=> false
p v2.between?(v1, v3) #=> true

参考