class Summer
@@defines = {}
class Bleak
class BleakError < RuntimeError; end
class TermProcNotDefinedError < BleakError; end
class SuccProcNotDefinedError < BleakError; end
def sum(term, a, succ, b)
return 0 if a > b
term.call(a) + sum(term, succ.call(a), succ, b)
end
def term(&block)
@term_proc = block
end
def succ(&block)
@succ_proc = block
end
def finale(&block)
@finale_proc = block
end
def run(a, b)
raise TermProcNotDefinedError unless @term_proc.is_a?(Proc)
raise SuccProcNotDefinedError unless @succ_proc.is_a?(Proc)
x = sum(@term_proc, a, @succ_proc, b)
x = @finale_proc.call(x) if @finale_proc.is_a?(Proc)
x
end
end
def self.define(symbol, &block)
o = @@defines[symbol] = Bleak.new
yield o
instance_eval <<-EOT
def self.#{symbol}_sum(a, b)
sum(#{symbol.inspect}, a, b)
end
EOT
end
def self.sum(symbol, a, b)
@@defines[symbol].run(a, b)
end
end
The definitions
Summer.define(:pi) do |pi|
pi.term do |x|
(1.0 / (x * (x + 2)))
end
pi.succ do |x|
(x + 4)
end
pi.finale do |x|
(x * 8)
end
end