昨日(id:rahaema:20080708)、
- 3 + Complex(5, 6)のすごさ(coerce規約)
と書いたのですが、
- Complex(5, 6) + 3
だったら添付ライブラリであるComplexクラスの、+メソッドでうまくやってるんだろうと思えるのですが、やっぱり、3 + Complex(5, 6)と書けるのはすごいなぁというか不思議な感じがします。
不思議に思ったので、まずcomplex.rbを見てみました。
def + (other) if other.kind_of?(Complex) re = @real + other.real im = @image + other.image Complex(re, im) elsif Complex.generic?(other) Complex(@real + other, @image) else x , y = other.coerce(self) x + y end end
if〜elsifまでで、Complex同士、Integer, Float, Rationalとの加算ができるようです。ここまでは予想通りなのですが、else節にother.coerce(self)が出てきました。
今度は、numeric.cを見てみました。
static VALUE fix_plus(x, y) VALUE x, y; { if (FIXNUM_P(y)) { long a, b, c; VALUE r; a = FIX2LONG(x); b = FIX2LONG(y); c = a + b; r = LONG2NUM(c); return r; } if (TYPE(y) == T_FLOAT) { return rb_float_new((double)FIX2LONG(x) + RFLOAT(y)->value); } return rb_num_coerce_bin(x, y); }
yが、FIXNUM,FLOATでなければ、rb_num_coerce_bin(x, y)という処理をしているようです。これがcoerce規約の入口だと思うのですが、あとは、難しくて入口の扉を開くことはできませんでした…。
ちょっと妥協して、Complex < Numeric だからこんなこともできるんだと今は納得することにします…。
最後にcoerceメソッドについて、irbで試してみました。
mmasa@debian:~$ irb -rcomplex irb(main):001:0> Complex(5,6).coerce(3) => [Complex(3, 0), Complex(5, 6)]