Fix `Rational#==(Complex)`
Consider a Numreic class like `Complex` that does not have `<=>` but `==`
works (`0i == 0r` is `true`).
MODIFY
mrbgems/mruby-rational/mrblib/rational.rb
mrbgems/mruby-rational/mrblib/rational.rb
@@ -62,6 +62,19 @@ class Rational < Numeric
nil
end
end
+
+ def ==(rhs)
+ if rhs.is_a?(Integral)
+ return numerator == rhs if denominator == 1
+ rhs = Rational(rhs)
+ end
+
+ if rhs.is_a?(Rational)
+ numerator * rhs.denominator == denominator * rhs.numerator
+ else
+ rhs == self
+ end
+ end
end
class Numeric

MODIFY
mrbgems/mruby-rational/test/rational.rb
mrbgems/mruby-rational/test/rational.rb
+class UserDefinedNumeric < Numeric
+ def initialize(n)
+ @n = n
+ end
+
+ def <=>(rhs)
+ return nil unless rhs.respond_to?(:to_i)
+ rhs = rhs.to_i
+ rhs < 0 ? nil : @n <=> rhs
+ end
+
+ def inspect
+ "#{self.class}(#{@n})"
+ end
+end
+
+class ComplexLikeNumeric < UserDefinedNumeric
+ def ==(rhs)
+ @n == 0 && rhs == 0
+ end
+
+ undef <=>
+end
+
def assert_rational(exp, real)
assert_float exp.numerator, real.numerator
assert_float exp.denominator, real.denominator
@@ -17,7 +41,7 @@ def assert_cmp(exp, o1, o2)
if exp == (o1 <=> o2)
pass
else
- flunk "", " Expected #{o1.inspect} <=> #{o2.inspect} to be #{exp}"
+ flunk "", " Expected #{o1.inspect} <=> #{o2.inspect} to be #{exp}."
end
end
@@ -106,6 +130,13 @@ assert 'Rational#==, Rational#!=' do
assert_equal_rational(false, Rational(2,1), 1r)
assert_equal_rational(false, Rational(1), nil)
assert_equal_rational(false, Rational(1), '')
+ assert_equal_rational(true, 0r, UserDefinedNumeric.new(0))
+ assert_equal_rational(true, 1r, UserDefinedNumeric.new(1))
+ assert_equal_rational(false, 1r, UserDefinedNumeric.new(2))
+ assert_equal_rational(false, -1r, UserDefinedNumeric.new(-1))
+ assert_equal_rational(true, 0r, ComplexLikeNumeric.new(0))
+ assert_equal_rational(false, 1r, ComplexLikeNumeric.new(1))
+ assert_equal_rational(false, 1r, ComplexLikeNumeric.new(2))
end
assert 'Fixnum#==(Rational), Fixnum#!=(Rational)' do
@@ -123,21 +154,6 @@ assert 'Float#==(Rational), Float#!=(Rational)' do
end
assert 'Rational#<=>' do
- num = Class.new(Numeric) do
- def initialize(n)
- @n = n
- end
-
- def <=>(rhs)
- rhs = rhs.to_i
- rhs < 0 ? nil : @n <=> rhs
- end
-
- def inspect
- "num(#{@n})"
- end
- end
-
assert_cmp(-1, Rational(-1), Rational(0))
assert_cmp(0, Rational(0), Rational(0))
assert_cmp(1, Rational(1), Rational(0))
@@ -158,10 +174,12 @@ assert 'Rational#<=>' do
assert_cmp(-1, Rational(1,2), Rational(2,3))
assert_cmp(-1, Rational(1,2), Rational(2,3))
assert_cmp(nil, 3r, "3")
- assert_cmp(1, 3r, num.new(2))
- assert_cmp(0, 3r, num.new(3))
- assert_cmp(-1, 3r, num.new(4))
- assert_cmp(nil, Rational(-3), num.new(5))
+ assert_cmp(1, 3r, UserDefinedNumeric.new(2))
+ assert_cmp(0, 3r, UserDefinedNumeric.new(3))
+ assert_cmp(-1, 3r, UserDefinedNumeric.new(4))
+ assert_cmp(nil, Rational(-3), UserDefinedNumeric.new(5))
+ assert_raise(NoMethodError) { 0r <=> ComplexLikeNumeric.new(0) }
+ assert_raise(NoMethodError) { 1r <=> ComplexLikeNumeric.new(2) }
end
assert 'Fixnum#<=>(Rational)' do

Fix `Rational#==(Complex)`

Consider a Numreic class like `Complex` that does not have `<=>` but `==`
works (`0i == 0r` is `true`).