[ruby-dev:39851] Time.now + str と #to_r

From: Yukihiro Matsumoto <matz@...>
Date: 2009-12-07 03:42:17 UTC
List: ruby-dev #39851
まつもと ゆきひろです

[ruby-core:23729]で指摘されたTimeとstringの加算がエラーにな
らない理由は、1.9でRationalが組み込まれたことで、

  * String#to_rが提供された
  * String#to_rはRationalとして解釈できない文字列に0を返す
  * timeが内部計算にRationalを使うようになった
  * timeがオペランドの変換にto_rを使うようになった

というコンボによって発生しました。いちおう、Time#+の正当な引
数として文字列(T_STRINGおよびto_strを持つオブジェクト)を外す
という対応を行いましたが、生煮え感がぬぐえません。

気に入らない原因を改めて考えてみましたが、どうやら以下の複合
のようです。

 * to_rという名前はよくない。rがrationalだかregexpだかrange
   だかわからない。長年の利用でもう定着してしまった
   s(string), i(integer), a(array)は仕方がないとしても、これ
   以上1文字to_?メソッドを増やすべきではない。この点では
   BigDecimal#to_dも同罪

 * Timeがto_rを使っているのもよくない。名前が良くないことに加
   えて、オペランドの暗黙の型変換のための(to_intのような)メ
   ソッドは、明示的な型変換を行う(to_iのような)メソッドと分
   離されているべきであろう。

 * しかし、Rationalは現状そのようなメソッドを提供していない
   (実装はある)。

 * そもそもto_iとto_intのような、明示的な変換と暗黙的な変換の
   ペアのための統一的なネーミングルールがない。

ということで、手元で以下のような変更を行う(かなり大きめの)パッ
チを作ってみましたが、これでも満足できません。

 * to_rとto_dを削除
 * 明示的な変換はas_xxx、暗黙的な変換はto_xxx
 * to_iなどにはas_intという別名
 * 基本的クラス(int,str,ary)以外はフルネーム.to_lower
 * よってTimeの変換にはto_rationalを使う

このパッチの最大の弱点は作った本人もtoとasがどっちがどっちだ
か忘れてしまうというところでしょう。また、変更の規模が大きい
ので1.9.2には手遅れという感もあります。私としてはto_rやto_dが
これ以上広まらないうちに手を打ちたいのですが、そのへんは
Yuguiさんの判断に任せるとして。

で、明示的な変換と暗黙的な変換のための命名原則はどのようなも
のがよいのか、という点について、いろいろとご意見を聞かせてく
ださいませ。あるいは上記問題のまったく別の解決方法が思いつい
た場合には、それも聞きたいです。数の相互型変換を行うようなシ
ステムの構築という解もありえるかもしれません。

あと、現状では明示的な変換の方は

  "foo".to_i # => 0

のような、わりとカジュアルな変換をしていますが、これはうれし
いことが少ないので、今後新たに追加する場合は(Raional も含め
て)、エラーをあげるべきではないかと思うようになりましたが、こ
れはまた別の話として議論すべきでしょう。

                                まつもと ゆきひろ /:|)

In This Thread

Prev Next