# In Ruby, how does coerce() actually work?

**URL:** <https://www.ruby-forum.com/t/in-ruby-how-does-coerce-actually-work/188307>\
**Category:** Ruby\
**Created:** [May 10, 2010, 2:11am UTC](https://www.ruby-forum.com/t/in-ruby-how-does-coerce-actually-work/188307 "2010-05-10T02:11:50Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![winterheat](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/w/7993a0/32.png) [@winterheat](https://www.ruby-forum.com/u/winterheat)\
**Post date:** [May 10, 2010, 2:11am UTC](https://www.ruby-forum.com/t/in-ruby-how-does-coerce-actually-work/188307/1 "2010-05-10T02:11:50Z")

</div>

It is said that when we have a class Point and knows how to perform  
point \* 3 like the following:

```
class Point

  def initialize(x,y)
    @x, @y = x, y
  end

  def *(c)
    Point.new(@x * c, @y * c)
  end

end

point = Point.new(1,2)
p point
p point * 3

```

Output:

```
#<Point:0x336094 @x=1, @y=2>
#<Point:0x335fa4 @x=3, @y=6>

```

but then,

```
3 * point

```

is not understood:

```
Point can't be coerced into Fixnum (TypeError)

```

So we need to further define an instance method `coerce`:

```
class Point
  def coerce(something)
    [self, something]
  end
end

p 3 * point

```

Output:

```
#<Point:0x3c45a88 @x=3, @y=6>

```

So it is said that

```
3 * point

```

is the same as

```
3.*(point)

```

that is, the instance method `*` takes an argument `point` and invoke on  
the object `3`.

Now, since this method `*` doesn’t know how to multiply a point, so

```
point.coerce(3)

```

will be called, and get back an array:

```
[point, 3]

```

and then `*` is once again applied to it, is that true?

```
point * 3

```

which is the same as

```
point.*(3)

```

and now, this is understood and we now have a new Point object, as  
performed by the instance method `*` of the Point class.

The question is:

1. who invokes point.coerce(3) ? Is it Ruby automatically, or is it  
some code inside of `*` method of Fixnum by catching an exception? Or  
is it by case statement that when it doesn’t know one of the known  
types, then call coerce?

2. Does coerce always need to return an array of 2 elements? Can it be  
no array? Or can it be an array of 3 elements?

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) Who  
does it? Is it done by Ruby or is it done by code in Fixnum? If it is  
done by code in Fixnum, then it is a “convention” that everybody follows  
when doing a coerce?

So could it be the code in `*` of Fixnum doing something like this:

```
class Fixnum

  def *(something)
  if (something.is_a? ...)
  else if ... # other type / class
  else if ... # other type / class
  else
  # it is not a type / class I know
    array = something.coerce(self)
    return array[0].*(array[1]) # or just return array[0] *

```

array[1]  
end  
end

```
end

```

1. So it is really hard to add something to Fixnum’s instance method  
`coerce`? It already has a lot of code in it and we can’t just add a  
few lines to enhance it (but will we ever want to?)

2. The coerce() in the Point class is quite generic and it works with  
`*` or `+` because they are transitive. What if it is not transitive,  
such as if we define Point minus Fixnum to be:

---

<div class="post-metadata">

**Author:** ![winterheat](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/w/7993a0/32.png) [@winterheat](https://www.ruby-forum.com/u/winterheat)\
**Post date:** [May 10, 2010, 3:14pm UTC](https://www.ruby-forum.com/t/in-ruby-how-does-coerce-actually-work/188307/2 "2010-05-10T15:14:13Z")

</div>

2010/5/10 Jian L. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

> ```
> Point.new(@x * c, @y * c)
> 
> ```
> 
> #\<Point:0x336094 @x=1, @y=2\>  
> So we need to further define an instance method `coerce`:
> 
> class Point  
> def coerce(something)  
> [self, something]  
> end  
> end

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](http://blog.rubybestpractices.com/posts/rklemme/019-Complete_Numeric_Class.html)

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

The latter.

> 1. Does coerce always need to return an array of 2 elements? Can it be  
> no array? Or can it be an array of 3 elements?

It always needs to return an array of two elements - that’s the  
contract.

> 1. 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? Is it done by Ruby or is it done by code in Fixnum?

The latter.

> If it is  
> 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.

> 1. So it is really hard to add something to Fixnum’s instance method  
> `coerce`? It already has a lot of code in it and we can’t just add a  
> 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.

> 1. The coerce() in the Point class is quite generic and it works with  
> `*` or `+` because they are transitive. What if it is not transitive,  
> such as if we define Point minus Fixnum to be:

I think you confused “transitive” and “commutative”.

> **[Commutative property](https://en.wikipedia.org/wiki/Commutative)**
>
> In mathematics, a binary operation is commutative if changing the order of the operands does not change the result. It is a fundamental property of many binary operations, and many mathematical proofs depend on it. Most familiar as the name of the property that says something like "3 + 4 = 4 + 3" or "2 × 5 = 5 × 2", the property can also be used in more advanced settings. The name is needed because there are operations, such as division and subtraction, that do not have it (for example, "3 − 5 ...

> **[Transitive relation](https://en.wikipedia.org/wiki/Transitive_relation)**
>
> In mathematics, a relation R on a set X is transitive if, for all elements a, b, c in X, whenever R relates a to b and b to c, then R also relates a to c. Each partial order as well as each equivalence relation needs to be transitive.
> All definitions tacitly require the homogeneous relation 
>   
>     
>       
> R
>       
>     
> {\\displaystyle R}
>   
> be transitive: for all 
>   
>     
>       
> a
> ,
> b
> ,
> c
> ,
>       
>     
> {\\displaystyle a,b,c,}
>   
> i...

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

Kind regards

robert
