2010/5/10 Jian Lin <blueskybreeze / gmail.com>:
> It is said that when we have a class Point and knows how to perform
> point * 3 like the following:
>
>   >
>   >     >  
>
>   
>    
>  
>
>  
>
>   
>   >   >
> Output:
>
> <Point:0x336094 @x=1, @y=2>
> <Point:0x335fa4 @x=3, @y=6>
>
> but then,
>
>  * point
>
> is not understood:
>
>      >
> So we need to further define an instance method `coerce`:
>
>
>   >   >  
>  
>  

There is no type checking and conversion.  Normally you would also
return the argument first but in this case exchanging the order seems
OK since the multiplication is not really symmetric.

The std lib does it like this:

irb(main):001:0> 1.2.coerce 3
=> [3.0, 1.2]
irb(main):002:0>


Please see my blog post for a complete example:
http://blog.rubybestpractices.com/posts/rklemme/019-Complete_Numeric_Class.html

> The question is:
>
> 1) who invokes point.coerce(3) ?       
> some code inside of `*` method of Fixnum by catching an exception?  > is it by case statement that when it doesn't know one of the known
> types, then call coerce?

The latter.

> 2) Does coerce always need to return an array of 2 elements?    
> no array?      
It always needs to return an array of two elements - that's the contract.

> 3) And is the rule that, the original operator (or method) `*` will then
> be invoked on element 0, with the argument of element 1? element 0 and
> element 1 are the two elements in that array returned by coerce)

Exactly.

>Who does it?            
The latter.

>   
> done by code in Fixnum, then it is a "convention" that everybody follows
> when doing a coerce?

I'd rather say it's the contract of #coerce but you can call it a
"convention" as well.

> 4) So it is really hard to add something to Fixnum's instance method
> `coerce`?        > few lines to enhance it (but will we ever want to?)

You do not need to add to Fixnum's coerce.  Rather you add to your
operator implementation.

> 5) The coerce() in the Point class is quite generic and it works with
> `*` or `+` because they are transitive.     > such as if we define Point minus Fixnum to be:
>
>   
>      
> 0 - point # ==> to give -80,-80)

I think you confused "transitive" and "commutative".
http://en.wikipedia.org/wiki/Commutative
http://en.wikipedia.org/wiki/Transitive_relation

Commutativity is the exact reason for having #coerce.  Please see the blog post.

Kind regards

robert

-- 
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/