Sunday, November 08, 2009

Calculator Kata revisited

Just as a follow-on, I went back to the Calculator Kata and applied a functional Ruby approach with the rule of no mutable state allowed. I was inspired by Tom Stuart's Thinking Functionally in Ruby talk.

This time I create a reusable Proc for scanning the expression according to the regex that extracts [left_operand, operator, right_operand] arrays. I evaluate the expression with reduce, using the evaluation of the first equation in the expression as the initial value, and then applying that as the left hand side of all other equations in the expression. The drop(1) call removes the first element of the parsed expression so that the reduce call can operate on the second and all subsequent equations in the expression. Since the initial value passed to reduce is the evaluation of the first equation, the memo passed to all evaluations in the reduce block is the last evaluated result.

module Calculator
def self.calculate(expression)
raise ArgumentError, 'Must be a string expression' unless expression.is_a? String
raise ArgumentError, 'Must be numeric arithmetic' unless expression =~ pattern
sets = lambda { expression.scan(pattern) }
sets.call.drop(1).
reduce(evaluate(*sets.call.first)) do |last_result, equation|
evaluate(last_result, *equation[1..2])
end
end
private
def self.evaluate(left, operator, right)
eval(left + operator + right).to_s
end
def self.pattern
/(\d+)\s?([\+\-\*\/])\s*(?=(\d+))/
end
end
view raw snippet.rb hosted with ❤ by GitHub

The above code passes the same spec as I included in the previous post

No comments: