khpeek - 9 months ago 23

Ruby Question

I'm writing a Reverse Polish Notation (RPN) calculator which, until now, looks like this:

`class RPNCalculator`

attr_accessor :numbers, :value

def initialize

@numbers = []

@value = nil

end

def push(number)

@numbers.push(number)

end

def plus

if value.nil?

number1=@numbers.pop

number2=@numbers.pop

@value = number1 + number2

else

@value += @numbers.pop

end

end

# minus_proc = Proc.new {|a,b| a - b}

def minus

number1=@numbers.pop

number2=@numbers.pop

@value = number2 - number1

# operate_on_two_numbers(minus_proc)

end

def operate_on_two_numbers(&prc)

number1=@numbers.pop

number2=@numbers.pop

@value = prc.call(number1,number2)

end

end

For example, the following commands

`calculator=RPNCalculator.new`

calculator.push(5)

calculator.push(8)

calculator.plus

p calculator.value

produce the number "13".

This is how it's supposed to work, but there seems to be a lot of repetition in the code. For example, the "plus" and "minus" functions are largely the same; only a "+" and "-" inside the code differs.

I'd like to try to define a (private) method which accepts as an argument an operation which operates on two numbers, such as "+", "-", "*", or "/". It would be nice to use 'shortcut notation' like the shortcut

`.inject(:+)`

I've given it a try with the commented-out lines and the method

`operate_on_two_numbers`

Answer

You could use any arithmetic operator here in the same manner

```
def operate_on_two_numbers(a, b, op)
a.send(op, b)
end
operate_on_two_numbers(1, 2, :+)
#=> 3
operate_on_two_numbers(1, 2, :-)
#=> -1
```

Here's what your full code could look like

```
class RPNCalculator
attr_accessor :numbers, :value
def initialize
@numbers = []
@value = nil
end
def push(number)
@numbers.push(number)
end
def plus
operate_on_two_numbers(:+)
end
def minus
operate_on_two_numbers(:-)
end
private
def operate_on_two_numbers(op)
number1=@numbers.pop
number2=@numbers.pop
@value = number1.send(op, number2)
end
end
calculator=RPNCalculator.new
#=> #<RPNCalculator:0x00000002efe460 @numbers=[], @value=nil>
calculator.push(5)
#=> [5]
calculator.push(8)
#=> [5, 8]
calculator.plus
#=> 13
calculator.value
#=> 13
```