# Commutativity of '\*'

**URL:** <https://rubytalk.org/t/commutativity-of/11321>\
**Category:** ruby-talk\
**Created:** [2 May 2004 11:23 UTC](https://rubytalk.org/t/commutativity-of/11321 "2004-05-02T11:23:59Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![Stephan\_Kamper3](https://avatars.discourse-cdn.com/v4/letter/s/d9b06d/32.png) [@Stephan\_Kamper3](https://rubytalk.org/u/Stephan_Kamper3)\
**Post date:** [2 May 2004 11:23 UTC](https://rubytalk.org/t/commutativity-of/11321/1 "2004-05-02T11:23:59Z")

</div>

Hi all,

say I have a new class Foo which provides \* as a multiplicative method.  
Now, given the following lines:

def some\_operation\_using( lft, rgt )  
return "#{lft} times #{rgt}"  
end

class Foo

def \*( other )  
# do something  
res = some\_operation\_using( other, self )  
return res  
end

def to\_s  
return "a Foo thingy."  
end

end

# That given, the following lines will work

f = Foo.new  
puts f \* 42.0

# But this won’t. Instead I get:

# …/lm.rb:25:in `\*’: Foo can’t be coerced into Float (TypeError)

# from …/lm.rb:25

puts 42.0 \* f

What would be a (or even the) Ruby Way to get the last line to work?  
Some method to coerce a Foo into a Float? Or some hacking of Float  
itself? Like adding that, for example:

class Float  
alias old\_mult \*  
def \*( other )  
if other.class == Foo  
return other \* self  
else  
return self.old\_mult( other )  
end  
end  
end

That doesn’t seem to be terribly elegant, I think.

Any other way?

Happy rubying

Stephan

---

<div class="post-metadata">

**Author:** ![ts1](https://avatars.discourse-cdn.com/v4/letter/t/a8b319/32.png) [@ts1](https://rubytalk.org/u/ts1)\
**Post date:** [2 May 2004 11:43 UTC](https://rubytalk.org/t/commutativity-of/11321/2 "2004-05-02T11:43:20Z")

</div>

> # But this won't. Instead I get:  
> # .../lm.rb:25:in `\*': Foo can't be coerced into Float (TypeError)

Well, ruby is saying that it can coerce, learn it how to do it

One way to do it

svg% cat b.rb  
#!/usr/bin/ruby  
def some\_operation\_using( lft, rgt )  
&nbsp;&nbsp;&nbsp;"#{lft} times #{rgt}"  
end

class Foo

&nbsp;&nbsp;&nbsp;def \*(other)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;# do something  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;res = some\_operation\_using( other, self )  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;res  
&nbsp;&nbsp;&nbsp;end

&nbsp;&nbsp;&nbsp;def coerce(other)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case other  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;when Numeric  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[self, other]  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;raise TypeError  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;end

&nbsp;&nbsp;&nbsp;def to\_s  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"a Foo thingy."  
&nbsp;&nbsp;&nbsp;end

end

f = Foo.new  
puts f \* 42.0  
puts 42.0 \* f  
svg%

svg% b.rb  
42.0 times a Foo thingy.  
42.0 times a Foo thingy.  
svg%

Guy Decoux

---

<div class="post-metadata">

**Author:** ![Robert](https://avatars.discourse-cdn.com/v4/letter/r/e95f7d/32.png) [@Robert](https://rubytalk.org/u/Robert)\
**Post date:** [2 May 2004 11:53 UTC](https://rubytalk.org/t/commutativity-of/11321/3 "2004-05-02T11:53:59Z")

</div>

“Stephan Kämper” [Stephan.Kaemper@Schleswig-Holstein.de](mailto:Stephan.Kaemper@Schleswig-Holstein.de) schrieb im  
Newsbeitrag [news:c72lo9$hi3jp$1@ID-96582.news.uni-berlin.de](mailto:news:c72lo9$hi3jp$1@ID-96582.news.uni-berlin.de)…

> Hi all,
> 
> say I have a new class Foo which provides \* as a multiplicative method.  
> Now, given the following lines:
> 
> def some\_operation\_using( lft, rgt )  
> return “#{lft} times #{rgt}”  
> end
> 
> class Foo
> 
> def \*( other )  
> # do something  
> res = some\_operation\_using( other, self )  
> return res  
> end
> 
> def to\_s  
> return “a Foo thingy.”  
> end
> 
> end
> 
> # That given, the following lines will work
> 
> f = Foo.new  
> puts f \* 42.0
> 
> # But this won’t. Instead I get:
> 
> # …/lm.rb:25:in `\*': Foo can’t be coerced into Float (TypeError)
> 
> # from …/lm.rb:25
> 
> puts 42.0 \* f
> 
> What would be a (or even the) Ruby Way to get the last line to work?  
> Some method to coerce a Foo into a Float? Or some hacking of Float  
> itself? Like adding that, for example:
> 
> class Float  
> alias old\_mult \*  
> def \*( other )  
> if other.class == Foo  
> return other \* self  
> else  
> return self.old\_mult( other )  
> end  
> end  
> end
> 
> That doesn’t seem to be terribly elegant, I think.
> 
> Any other way?

You want coerce. See my posting in thread “coerce(), what protocol to  
implement it” from 30 Apr.  
[http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/98791](http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/98791)

Kind regards

```
robert

```

---

<div class="post-metadata">

**Author:** ![Kristof\_Bastiaensen1](https://avatars.discourse-cdn.com/v4/letter/k/9fc29f/32.png) [@Kristof\_Bastiaensen1](https://rubytalk.org/u/Kristof_Bastiaensen1)\
**Post date:** [2 May 2004 19:33 UTC](https://rubytalk.org/t/commutativity-of/11321/4 "2004-05-02T19:33:58Z")

</div>

It is maybe not a good idea to reverse the order in coerce.  
It may work with \* and +, but you will get a problem when  
order matters, like in / (division):

#— including the above code —

class Foo  
def /(other)  
“divide #{self} by #{other}”  
end  
end

puts (f / 2)  
=\> “divide a Foo thingy. by 2”  
puts (2 / f)  
=\> “divide a Foo thingy. by 2”

#— end code —

Note that some classes which use \*, and don’t represent a number  
just give an error:

“string” \* 2  
=\> “stringstring”  
2 \* “string”  
=\> TypeError: String can’t be coerced into Fixnum

That behaviour is probably the best if you are not representing  
a number.

Kristof

> **···**
>
> On Sun, 02 May 2004 20:43:20 +0900, ts wrote:
> 
> > #!/usr/bin/ruby  
> > def some\_operation\_using( lft, rgt )  
> > “#{lft} times #{rgt}”  
> > end
> > 
> > class Foo
> > 
> > def \*(other)  
> > # do something  
> > res = some\_operation\_using( other, self )  
> > res  
> > end
> > 
> > def coerce(other)  
> > case other  
> > when Numeric  
> > [self, other]  
> > else  
> > raise TypeError  
> > end  
> > end
> > 
> > def to\_s  
> > “a Foo thingy.”  
> > end
> > 
> > end
> > 
> > f = Foo.new  
> > puts f \* 42.0  
> > puts 42.0 \* f  
> > svg%
> > 
> > svg% b.rb  
> > 42.0 times a Foo thingy.  
> > 42.0 times a Foo thingy.  
> > svg%
> > 
> > Guy Decoux
