String#to_i の引数(基数の指定)にみる Ruby のパージング

文字列(String)を整数(Integer)へ変換することでおなじみの String#to_i メソッド。このメソッドは、引数に整数値を指定すると、その値を文字列の基数とした上で整数変換を行う。この引数と、「引数指定時に括弧を省略できる」という Ruby の仕様によって、一見分かりにくい現象が起こるようだ*1

事例研究

いくつかの事例を見てみよう。

irb(main):001:0> "21".to_i(16)
=> 33

文字列 "21" が16進数であるとみなして整数変換している。当然結果は整数値の33だ。

irb(main):002:0> "21".to_i 16
=> 33

上記と同じことを行っている。違うのは引数の括弧を省略していることである。

irb(main):003:0> "21".to_i +16
=> 33

これは、文字列 "21" を整数値21に変換して、16を足しているのではない。+16 という整数値を to_i に引数として(括弧を省略して)与えているのである。よって、結果はまたも上記と同じである。

irb(main):004:0> "21".to_i+16
=> 37
irb(main):005:0> "21".to_i + 16
=> 37

そして上の2つは、これまでの例と異なり、「文字列 "21" を整数値21に変換して、16を足している」式である。

004の式では、+16 を to_i の括弧なし引数とは解釈できない。なぜなら、その解釈の場合、メソッド名と引数がくっついているという状況なわけで、そういう解釈はできないからである。

005の式では、左右の空白のおかげで + は二項演算と判断される。

irb(main):006:0> "21".to_i +16 + 1
=> 35

これは、「"21".to_i +16」の結果の33に1を足しているのではない。to_i に 「+16 + 1」(の結果の17)を引数として与えているのである。ゆえに結果は "21" を17進数とみなして整数値に直した35となる。

以下の例も参考になるだろう。

irb(main):001:0> puts 1 + 2 , 4
3
4
=> nil