Ruby の String#to_i と組み込み関数の Integer() は違う

2007/10/06 10:37am

文字列から数値への変換に String.to_i を使っていると、思わぬ問題に出くわすことがある。

Ruby リファレンスマニュアルには、

整数とみなせない文字があればそこまでを変換対象とします。変換対象が 空文字列であれば 0 を返します。

このように説明されているが、これをそのまま解釈すると、以下のような挙動が予想できる。

irb(main):001:0> "10".to_i       => 10
irb(main):002:0> "10fixnum".to_i => 10
irb(main):003:0> "".to_i         => 0

ただ、次のような挙動は意外だった。

irb(main):001:0> "  10".to_i   => 10
irb(main):002:0> "fixnum".to_i => 0

最初の例は「文字列中の先頭の空白文字は無視される」と推測できるが、次の例はどうだろうか。明らかに数値ではない文字列の場合はエラーになりそうだが、この場合、

という挙動らしい。

変換できない場合はエラーにする

変換できないときに 0 を返すのはコードをシンプルにできるが、バグの原因にもなりやすい。

変換できない場合はエラーにしたいところだが、Ruby の Time.parse で文字列を Time に変換するときのエラーチェックと同様、String.to_i にはエラーを検出する仕組みがない。

どうするか、というと組み込み関数の Integer を使う。

irb(main):001:0> Integer("10fixnum")
ArgumentError: invalid value for Integer: "10fixnum"
        from (irb):7:in `Integer'
        from (irb):7
        from :0

リファレンスマニュアルにもあるように、変換できない場合は、例外 ArgumentError が発生する。