どうでもいいことだが気になったので試してみた。
ruby2.6.0
hash1 = (1..5).each_with_object({}) { |i,hash| hash[0.0/0.0] = i }
#=> {NaN=>1, NaN=>2, NaN=>3, NaN=>4, NaN=>5}
hash1[0.0/0.0] #=> nil
nan = 0.0/0.0
hash2 = (1..5).each_with_object({}) { |i,hash| hash[nan] = i }
#=> {NaN=>5}
hash2[nan] #=> 5
同一のオブジェクトでない限りはキーが別物と扱われる(当然キーを指定して値を取り出せない)。
ふと気になったのは「Hashのキーの同一性判定に #eql?
が使われる」という話から。浮動小数点数の非数(Not a Number; NaN)は自身と比較して偽になるので、この理屈ではHashのキーにすると全て別物と判断されてしまうはず。実際、最初の例はそのような結果になった。
しかしもう少し試してみたら、2番目の例のように同一のオブジェクトを使ったら同じキーと判断された。 #eql?
の前に #equal?
相当の処理を挟んでいる?
ちなみに #eql?
を内部で使っているメソッドとして Array#uniq
などもあり、やはり非数だとHashのキーと同じような同一性判定に見える。
参考までに、QiitaにおいてRubyの非数を扱っている記事を少々。