Commutativity of '*'

  • Thread starter Stephan Kämper
  • Start date
S

Stephan Kämper

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
 
T

ts

"S" == =?ISO-8859-1?Q?Stephan K=E4mper?= <ISO-8859-1> writes:

S> # But this won't. Instead I get:
S> # .../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 )
"#{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
 
R

Robert Klemme

Stephan Kämper said:
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

Kind regards

robert
 
K

Kristof Bastiaensen

#!/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

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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,145
Messages
2,570,826
Members
47,371
Latest member
Brkaa

Latest Threads

Top