Class equality with coercion

I created this class based on predefined tests

class Roman
  include Comparable
  ROMAN_NUMBERS = { 1000 => "m", 900 => "cm", 500 => "d", 400 => "cd", 
      100 => "c", 90 => "xc", 50 => "l", 40 => "xl", 10 => "x", 9 => "ix", 
      5 => "v", 4 => "iv", 1 => "i" }

  def initialize(number)
    @number = number
  end

  def coerce(other)
    if Integer === other
      [ other, @number ]
    else
      [ Float(other), Float(@number) ]
    end
  end

  def <=>(n)
    @number <=> n
  end

  def -(n)
    Roman.new(@number - n)
  end 

  def to_s
    roman = ''
    ROMAN_NUMBERS.each do |value, letter|
      roman << letter * (@number / value)
      @number = @number % value
    end
    roman
  end
end

but I'm still failing this one

it "should support substraction" do
  (Roman.new(5) - Roman.new(3)).should == 2
  (Roman.new(4) - Roman.new(1)).should == 3
  (Roman.new(4) - 2).should == 2
  res = 6 - Roman.new(1)
  res.should == 5
  (res.kind_of? Roman).should be true
end

The problem is, that res is "kind of" Fixnum. How's that possible? How to make it pass the test?

Answers


The problem is that 6 - Roman.new(1) is the same as 6.-(Roman.new(1)) i.e. it is calling the built in subtraction method of Fixnum. Since Fixnum doesn't know about your Roman class, this calls your coerce method.

But you defined coerce to return a Fixnum in this case! The solution is to coerce the other operand, rather than self.

def coerce other
  [self.class.new(other), self]
end

But if you try this with your code, you'll get a stack error! That's because it's now coercing both operands into instances of Roman and it still doesn't know how to subtract them. You should redefine your subtraction method to handle those cases.

attr_reader :number
def - n
  return Roman.new(@number - n.number) if n.is_a? Roman
  Roman.new(@number - n)
end

Need Your Help

InfoPath 2010 forms do not open in the Browser using IE8

sharepoint-2010 infopath2010

If the user has InfoPath installed on their PC the form will default to open in InfoPath. This is not desirable. All forms should open in the browser not in InfoPath. Why? Because some users in the

R: How come that "is" is TRUE, but "as" is impossible?

r

The class "ecdf" inherits from the class "stepfun". If f is such an empirical cumulative density function,