はじめに
== / === / equal? / eql? は別物のようです。
==:値が等しいかを返す
p "foo" == "foo" #=> true
p 4 == 4 #=> true
p 4 == 4.0 #=> true
===:値を含むかを返す
厳密には誤った用法かもしれませんが、大枠は「含む」イメージで正しいと思います。
Rubyリファレンスマニュアル
以下のように説明されています。
case 式で使用されるメソッドです。
このメソッドは case 式での振る舞いを考慮して、各クラスの性質に合わせて再定義すべきです。
デフォルトでは内部で Object#== を呼び出します。
Range#=== は主に case 式での比較に用いられます。
# 左辺クラスのインスタンスであるかを返す
p String === "foo" #=> true
# 左辺範囲オブジェクトに含まれているかを返す
p (1..5) === 4 #=> true
p (1..5) === 4.0 #=> true
# == と同じ
p "foo" === "foo" #=> true
p 4 === 4 #=> true
p 4 === 4.0 #=> true
equal?:object_idが一致するかを返す
Rubyリファレンスマニュアル
p "foo".equal?("foo") #=> false
p :foo.equal?(:foo) #=> true
p 4.equal?(4) #=> true
p 4.equal?(4.0) #=> false
eql?
Rubyリファレンスマニュアル
p "foo".eql?("foo") #=> true
p :foo.eql?(:foo) #=> true
p 4.eql?(4) #=> true
p 4.0.eql?(4) #=> false
比較対象は==だと思います。
==:1 == 1.0 => true
eql?:1.eql?(4.0) => false
eql?は、同値であっても型が違うとfalseを返します。
余談:JavaScriptとの違い
JavaScriptでは、== / === は以下の意味を持ちます。
-
==:ゆるい等価性 -
===:厳密な等価性
console.log(1 == "1") //true
console.log(1 === "1") //false
そのため、基本的には===を使います。
おわりに
Rubyは「別の名前だけど同じ挙動」というメソッドが多いです。
(lengthとsize・reduceとinjectなど)
今回は、それぞれが「似た名前だけど別の挙動」でしたね。
以上、等価性にまつわるメソッドについてでした。