事の発端は、@noliliさんのつぶやき。
Optional同士の比較演算はなぜできるのか?
自分も興味を持ったので、さっそく検証用に新しいPlaygroundを作成。Bool?型の変数を2つ用意して、等価演算と大小の比較演算をそれぞれ試してみます。
nilの可能性のある値同士で、等価演算(==, !=)はできるけど、大小の比較(<, >など)はエラーになる。直感的です。
ここまで確認して、noliliさんに返信します。
@nolili nilと等しいかどうかは判定できるから等価系の演算子(==, !=)は定義されている、って感じじゃないでしょうか。大小の比較はできないからエラーになります。 pic.twitter.com/JAHx2vvkJK
— cocopon (@cocopon) March 20, 2015
話はそう単純ではありませんでした。 Int?
型だと大小の比較もできるというのです。
そ、そんなはずは…。だって、 nil
と数値を比較して、どっちが大きいとか小さいとかないでしょう?実際に試してみると…。
本当だ。マジだ。しかもちゃんと判定結果がBoolで返ってきています。
@nolili うほーほんとだ!!
— cocopon (@cocopon) March 20, 2015
さらに色々試してみます。
nil
は Int.min
より小さいそうですよ。そう言われましても…。
そもそも、 nil
になりうる値同士の比較演算って本当に意図した仕様なのでしょうか?途中から参戦した@nakiwoさんが、Swiftの深底を探っていきます。
@cocopon @nolili これですかね。
— Yuichi Fujishige (@nakiwo) March 20, 2015
func <<T : _Comparable>(lhs: T?, rhs: T?) -> Bool
nilは最弱扱いっぽいです (要出典) pic.twitter.com/Evjy1aTss6
自分も後を追いかけ、この定義に辿りつきます。
大小比較可能な(= _Comparable
)Optional同士の <
比較演算は Bool
を返すと書かれています。 Int
は _Comparable
を実装しているので、きちんと定義されていることはわかりました。しかしいったい誰得なんでしょう。Optional同士の大小比較、あるとうれしいシーンが存在するのだろうか…?
先の検証からも推測できますが、比較演算においてどうやら nil
は最も小さい値( Int.min
よりも!)をとるようです。このあたりの仕様について公式資料を探してみるも見つからず。
型おじさん@orga_chemにも相談してみたところ、やはり裏付けは取れないものの、同様の考察がされているStack Overflowを見つけてくれました。
(本題から外れるため上ではさらっと流してしまいましたが、整数リテラルが Int?
に暗黙的に変換されているあたりも言及されています)
今回の調査で、Optional同士の比較演算がちゃんと定義されていることはわかりました。しかし、その演算結果の仕様についての公式な情報には辿りつけませんでした。疑問を整理すると、
どうなんでしょう、教えてエライ人。