I wouldn't have know it, either, had you not asked the original question.
:)


----- Original Message -----
>   def coerce(other)
>     if Complex.generic?(other)
>       return Complex.new(other), self
>     else
>       super
>     end
>   end
[snip]

What does #coerce? do.  What does that 'super' do?  In particular, how
does that solve the addition problem?
----------------------------

I don't know the general answers to these questions, but I think I
understand what is going on here.

When I say `2 + Complex(1,1)', Fixnum#+ is called.  Note that this is never
overridden, so this is the original Fixnum#+.  What I am guessing is that
Fixnum#+ first looks to see if you are adding another fixnum, or what.  If
it knows how to do the conversion so that a meaningful addition can be
performed, then it does.  If not, it calls `other.coerce(self)'.  (I am
guessing all of this, so please someone correct me if I am wrong.)  In this
case, it calls Complex#coerce.  It is expecting to get an array of two
objects back of "the right type", though it may not even know what that type
is.  Then it sends the original message (in this case, `+', in the previous
case, `plus') to the first element in the array.  In other words, if
coercing returns [a,b], then it calls `a.mesg(b)'.

So what does Complex#coerce do?  Well, I think that `return' is actually
returning an array.  (I personally find this notation confusing and
obnoxious... what's the point of this?)  However, notice what happened:  it
returned two Complexes!

I guess the idea behind coercing is that you can coerce *either way*.  In
this case, even though it is fixnum addition being called, after coercing
`2.+' gets an array of two complex numbers:  first the complex version of
itself (2), and then the original other complex number (Complex(1,1)).  Then
it gives up on itself (meaning the fixnum 2) and sends the object to it's
coerced self.  What's cool is that in general `coerce' could return two
Fixnums (coercing the other object into a Fixnum), or it could coerce the
Fixnum into something else (like we saw).

No weird overloading and aliasing... pretty damn slick.

I don't know what super does...  probably calls Numeric#coerce (if Complex
is a subclass of Numeric) or Kernel#coerce (which probably just generates an
exception in most (all?) cases).  I think the idea was to handle what
Complex knew how to handle, and to pass everything else on.  Even if it does
just generate an exception, at least it will be a familiar one.

Chris