Skip to content

Instantly share code, notes, and snippets.

@dasibre
Last active August 29, 2015 14:21
Show Gist options
  • Select an option

  • Save dasibre/0e2f7df41a2a31f6d605 to your computer and use it in GitHub Desktop.

Select an option

Save dasibre/0e2f7df41a2a31f6d605 to your computer and use it in GitHub Desktop.
Fluent Calculator
#Complex yet elegant
class Calc
{ zero: 0, one: 1, two: 2, three: 3, four: 4, five: 5, six: 6, seven: 7, eight: 8, nine: 9 }.each do |m, n|
define_method("#{m}") { @proc ? @proc.call(n) : (@number ||= n ; self ) }
end
{ plus: :+, minus: :-, times: :*, divided_by: :/ }.each do |m, o|
define_method("#{m}") { @proc ||= lambda { |a| @number.send(o, a) }; self }
end
end
class Calc
attr_accessor :first, :second, :operator
%w(zero one two three four five six seven eight nine).each_with_index do |method,value|
define_method(method) do
if first.nil?
self.first = value
self
else
self.second = eval("#{self.first} #{operator} #{value}")
end
end
end
def plus
@operator = "+"
self
end
def times
@operator = "*"
self
end
end
describe Calc do
describe "#zero" do
it 'returns corresponding digit 0' do
calc = Calc.new
expect(calc.zero).to be_a Calc
end
end
describe "#one" do
it 'returns corresponding digit 1' do
calc = Calc.new
expect(calc.one).to be_a Calc
end
end
describe "#two" do
it 'returns corresponding digit 2' do
calc = Calc.new
expect(calc.two).to be_a Calc
end
end
describe "#times" do
it 'returns 2 for 2 times one' do
calc = Calc.new
expect(calc.two.times.one).to eq(2)
end
end
describe "#plus" do
it 'returns sum of two numbers' do
calc = Calc.new
expect(calc.one.plus.two).to eq(3)
end
it 'returns a sum of 3 for 2 plus 1' do
calc = Calc.new
expect(calc.two.plus.one).to eq(3)
end
it 'returns a sum of 4 for two plus two' do
calc = Calc.new
expect(calc.two.plus.two).to eq(4)
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment