Mae向きなブログ

Mae向きな日記のブログ版。ようやくこちらに移行してきました。

初めてのRuby2

昨日(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)]