🗂

[Ruby] String、Regexクラスでの`===`の挙動の違い

に公開

以下のコードの挙動を検証します。

> 'hoge' === /h/
=> false

> /h/ === 'hoge' 
=> true

このように、String#===Regex#===は似ているようで挙動が違います。
ではなぜこうなるのでしょうか。

String#===の場合

> 'hoge' === /h/
=> false

class String (Ruby 3.2 リファレンスマニュアル)には、

other が文字列の場合、String#eql? と同様に文字列の内容を比較します。
other が文字列でない場合、 other.to_str が定義されていれば other == self の結果を返します。(ただし、 other.to_str は実行されません。) そうでなければ false を返します。

とあります。

/h/.classはRegexpクラスであり、/h/.to_strをするとNoMethodErrorが発生します。

> /h/.class
=> Regexp

> /h/.to_str
(irb):5:in `<main>': undefined method `to_str' for /h/:Regexp (NoMethodError)

したがって、結果はfalseになります。

Regex#===の場合

> /h/ === 'hoge' 
=> true

こちらはシンプルに正規表現として機能しています。

  • /h/という正規表現が、'hoge'という文字列のどれかにマッチするか検証している
  • この場合、'hoge'という文字列の中にhが含まれているのでtrueを返す

class Regexp (Ruby 3.2 リファレンスマニュアル)

Discussion