In ruby, I was messing around in the irb and found two code samples that should work the same but don't
"a" * 4 #this is "aaaa"
4 * "a" #this is "String can't be coerced into a Fixnum"
Doesn't this violate the commutative property of multiplication?
It does violate the commutative property, but that's not necessarily a problem, as the commutative property applies to the complex complex numbers in math. The reason "a" * 4
is not commutative in Ruby, as in most programming languages, is because a given type defines how it handles operators. So you could override the *
operator for the String
and Fixnum
class (but that's a VERY VERY bad idea in practice):
class String
def *(other)
if other.is_a?(Numeric)
puts "The method was called on an instance of String"
end
end
end
class Fixnum
def *(other)
if other.is_a?(Numeric)
puts "The method was called on an instance of Fixnum"
end
end
end
So if you were to call
"a" * 4
Then it would print "The method was called on an instance of String"
because that is equivalent to "a".*(4)
But this:
4 * "a"
Would print "The method was called on an instance of Fixnum"
because 4 * "a"
is equivalent to 4.*("a")
Here is a good article on operator overloading in Ruby.
Interesting side note: the commutative property actually doesn't apply to all numbers in math, the Quaterions and the Octonions both are not commutative.
Edit
If you wanted to, you could make the *
operator commutative (but that would be a bad idea). You could then define *
to swap the callee and the argument like such:
class Fixnum
def *(other)
other * self
end
end
That way, when ever you have 4 * "a"
it would actually do this: "a" * 4
. This would still work even if String#*
was later redefined. Monkey patching can often be useful, but in this case it's a terrible idea, I don't recommend doing this, it's just a cool proof of concept.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With