個人的に気になって調べた点のメモです。
仕様化されているかはまだ調べていないものの、少なくとも Ruby 2.2.3 はこの挙動でした。
結論
String#to_s
は同一のオブジェクトを返す (タイトル通り)
問題になるケース
たとえば以下のようなコード
query = str.dup
result = foo query
ここまで書いて str
が nil
になり得ることがわかったので、 .to_s
しようとなったときに、それが新たな String
オブジェクトを返すなら .dup
はいらないことになるし、そうでなければ残す必要がある。
(もちろん、str
をあとで使わなければ問題ない話なんだけど、それを完璧に保証するのは難しいので、変なバグを避けるために)
検証コード
a = 'foo'
b = a.to_s
p a.__id__ == b.__id__
# => true
a.upcase!
p [a, b]
# => ["FOO", "FOO"]
このように、.to_s
しただけでは同一のオブジェクトがそのまま変わるので、元の変数 a
に破壊的変更を行うと b
にも影響してしまう。
.dup
すればそういった問題は避けられる。
a = 'foo'
b = a.to_s.dup
p a.__id__ == b.__id__
# => false
a.upcase!
p [a, b]
# => ["FOO", "foo"]
あとで覚えてたら rubyspec とかも見てみる。