# Lambdas with object instances require 'benchmark' require 'rubygems' require 'metaid' require 'profile' class Proc def tag 'proc_' + object_id.to_s(36).sub('-', '_') end end class Object def const_tag 'C' + object_id.to_s(36).upcase.sub('-', '_') end end class C attr_accessor :name, :reverse def initialize(n) @name = n @reverse = @name.reverse end def self.define_proc(&block) tag = block.tag class_def(tag.to_sym, &block) unless instance_methods.include?(tag) tag.to_sym end def self.cache_constant(value) tag = value.const_tag class_eval "#{tag} = #{value.inspect}.freeze" rescue nil tag end def self.route(rule, &block) @@rules ||= [] @@rules.unshift [rule, block] compile_rules end def self.rule_to_statement(rule, block) tag = define_proc(&block) if Proc === rule cond = define_proc(&rule).to_s else # cond = rule.to_a.map {|kv| # "(@#{kv[0]} =~ #{Regexp.new(kv[1]).inspect})"}.join('&&') cond = rule.to_a.map {|kv| value_tag = cache_constant(Regexp.new(kv[1])) "(@#{kv[0]} =~ #{value_tag})"}.join('&&') end "return #{tag} if #{cond}\n" end def self.compile_rules code = "lambda {" @@rules.each {|r| code << rule_to_statement(r[0], r[1])} code += "}" class_def(:process, &eval(code)) end def t1 return "#{name} h" if name =~ /^h/ return "#{name} h" if (name =~ /^g/) && (reverse =~ /a$/) return "#{name} h" if name =~ /^f/ return "#{name} h" if name =~ /^e/ return "#{name} h" if name =~ /^d/ return "#{name} h" if name =~ /^c/ return "#{name} h" if name =~ /^b/ return "#{name} h" if name =~ /^a/ return "#{name} schatzie" if name =~ /^z/ return "#{name} mau" if name =~ /^s/ end end C.route(:name => '^s') {"#{name} mau"} C.route(:name => '^z') {"#{name} schatzie"} C.route(:name => '^a') {"#{name} a"} C.route(:name => '^b') {"#{name} b"} C.route(:name => '^c') {"#{name} c"} C.route(:name => '^d') {"#{name} d"} C.route(:name => '^e') {"#{name} e"} C.route(:name => '^f') {"#{name} f"} C.route(:name => '^g', :reverse => 'a$') {"#{name} g"} C.route(:name => '^h') {"#{name} h"} def assert(c) # raise "Assertion failed" if !c end def test(n = 5000) c1 = C.new('sharon') c2 = C.new('hag') n.times {assert c1.process == "sharon mau"} n.times {assert c2.process == "hag h"} end test