はじめに
最近とあるRubyのコードで foo?.!
という実装を見かけた。個人的にはあまり見かけない実装だったので気になって調べてみた。
検証環境
- Ruby 3.2.2
- irb 1.6.2
結論
-
.!
は論理否定をする返す -
.!
はインスタンスメソッドである
以降については調査した内容をまとめます。
.!
はどんな挙動をするのか
irbで foo.!
と !foo
の挙動を比較してみた結果、どちらも同じ挙動をすることが分かった。
foo.!
の場合
irb(main):001:0> true.!
=> false
irb(main):002:0> false.!
=> true
irb(main):003:0> nil.!
=> true
irb(main):004:0> "foo".!
=> false
!foo
の場合
irb(main):005:0> !true
=> false
irb(main):006:0> !false
=> true
irb(main):007:0> !nil
=> true
irb(main):008:0> !"foo"
=> false
!
はメソッドで演算子形式を呼び出せる
TrueClass
の親の親であるBasicObject Classに!
はインスタンスメソッドが定義されており、!
はメソッドであることがわかりました。
またRubyリファレンスマニュアルの演算子式の冒頭に以下の説明がありました。
プログラミングの利便のために一部のメソッド呼び出しと制御構造は演算子形式をとります。Rubyには以下にあげる演算子があります。
高い ::
[]
+(単項) ! ~
**
-(単項)
* / %
+ -
<< >>
&
| ^
> >= < <=
<=> == === != =~ !~
&&
||
.. ...
?:(条件演算子)
=(+=, -= ... )
not
低い and or
つまり !
はメソッドであり、演算子形式でも利用できるということなんですね。
同じように +
も Integer classにインスタンスメソッドとして定義されているので、以下のように演算子形式・メソッド形式の両方で呼ぶことができきます。
irb(main):016:0> 1 + 2
=> 3
irb(main):017:0> 1.+ 2
=> 3
なるほど〜、そういうことだったんですね。
※ もし誤りがありましたら指摘ください。
!foo
と foo?.!
はどっちが一般的か
Rubyリファレンスマニュアル
マニュアルではnot では、例として ! me
が案内されており、.!
の記載は見当たりませんでした。
Rubocop
Style/OperatorMethodCallというCopがあり、演算子をメソッド形式で呼ぶことは推奨されていませんでした。
Ruby Style Guide
Rubocopの元となっているRuby Style Guideでも Operator Method Callは非推奨と案内されていました。
これらの情報を踏まえると .!
表記は非推奨という判断で良さそうです。
まとめ
foo.!
について記法として推奨されているのか否か調べてみましたが、結果としては非推奨ということが分かってよかったです。非推奨ではありますが、実装的には問題なく利用することもできますので、好みで使用するのも有りだとは思います。ただ基本的にはRubocopやStyle Guideの方針に沿った方が良いと思いますので、特別な理由がない限りは foo.!
記法は使用せず、!foo
にしたいと思います。