<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array">
    <added>
      <filename>README</filename>
    </added>
    <added>
      <filename>test/supplement.rb</filename>
    </added>
    <added>
      <filename>test/wildcard.rb</filename>
    </added>
  </added>
  <modified type="array">
    <modified>
      <diff>@@ -2,71 +2,103 @@ require &quot;#{File.dirname(__FILE__)}/object&quot;
 
 class Functor
   
+  class NoMatch &lt; ArgumentError; end
+  
+  def self.cache_config(options={})
+    (@cache_config ||= { :size =&gt; 4_096, :base =&gt; 8 }).merge!(options)
+  end
+  
   module Method
-    def self.copy_functors( functors )
-      r = {} ; functors.each do | name, functor |
-        r[ name ] = functor.clone
-      end
-      return r
-    end
+    
     def self.included( k )
-      def k.functors
-        @__functors ||= superclass.respond_to?( :functors ) ? 
-          Functor::Method.copy_functors( superclass.functors ) : {}
+            
+      def k.functor_cache
+        @functor_cache ||= Hash.new { |hash, key| hash[key] = [ {},{},{},{} ] }
+      end
+      
+      def k.functor_cache_config(options={})
+        @functor_cache_config = ( @functor_cache_config || Functor.cache_config ).merge(options)
+      end
+      
+      def k.functor( name, *pattern, &amp;action )
+        _functor( name, false, *pattern, &amp;action)
       end
-      def k.functor( name, *args, &amp;block )
-        name = name.to_sym
-        ( f = ( functors[ name ] or 
-          ( functors[ name ] = Functor.new ) ) ).given( *args, &amp;block )
-        define_method( name ) { | *args | instance_exec( *args, &amp;f.match( *args ) ) } 
+      
+      def k.functor_with_self( name, *pattern, &amp;action )
+        _functor( name, true, *pattern, &amp;action)
       end
-      def k.functor_with_self( name, *args, &amp;block )
-        name = name.to_sym
-        ( f = ( functors[ name ] or 
-          ( functors[ name ] = Functor.new ) ) ).given( *args, &amp;block )
-        define_method( name ) { | *args | instance_exec( *args, &amp;f.match( self, *args ) ) } 
+      
+      # undefined methods beginning with '_' can be used as wildcards in Functor patterns
+      def k.method_missing(name, *args)
+        args.empty? &amp;&amp; name.to_s =~ /^_/  ?  lambda { |args| true }  :  super
       end
+      
+      private
+      
+      def k._functor( name, with_self=false, *pattern, &amp;action)
+        name = name.to_s
+        mc = functor_cache[name]  # grab the cache tiers for The Method
+        cache_size, cache_base = functor_cache_config[:size], functor_cache_config[:base]
+        c0_size, c1_size, c2_size, c3_size = cache_size * 4, cache_size * 3, cache_size * 2, cache_size
+        c1_thresh,c2_thresh,c3_thresh = cache_base.to_i, (cache_base ** 2).to_i, (cache_base ** 3).to_i
+        old_method = instance_method(name) if method_defined?( name ) # grab The Method's current incarnation        
+        define_method( name, action ) # redefine The Method
+        newest = instance_method(name) # grab newly redefined The Method
+        
+        # Recursively redefine The Method using the newest and previous incarnations
+        define_method( name ) do | *args |
+          match_args = with_self ? [self] + args : args
+          sig = match_args.hash
+          if meth = mc[3][sig]  # check caches from top down
+            meth[0].bind(self).call(*args)
+          elsif meth = mc[2][sig]
+            meth[1] += 1  # increment hit count
+            mc[3][sig] = mc[2].delete(sig) if meth[1] &gt; c3_thresh # promote sig if it has enough hits
+            (mc[0], mc[1], mc[2], mc[3] = mc[1], mc[2], mc[3], {}) if mc[3].size &gt;= c3_size # cascade if c3 is full
+            meth[0].bind(self).call(*args)
+          elsif meth = mc[1][sig]
+            meth[1] += 1
+            mc[2][sig] = mc[1].delete(sig) if meth[1] &gt; c2_thresh
+            mc[0], mc[1], mc[2] = mc[1], mc[2], {} if mc[2].size &gt;= c2_size
+            meth[0].bind(self).call(*args)
+          elsif meth = mc[0][sig]
+            meth[1] += 1
+            mc[1][sig] = mc[0].delete(sig) if meth[1] &gt; c1_thresh 
+            mc[0], mc[1] = mc[1], {} if mc[1].size &gt;= c1_size
+            meth[0].bind(self).call(*args)
+          elsif Functor.match?(match_args, pattern) # not cached?  Try newest meth/pat.
+            (mc[0], mc[1], mc[2], mc[3] = mc[1], mc[2], mc[3], {})  if mc[3].size &gt;= c3_size
+            mc[3][sig] = [newest, 0]  # methods are cached as [ method, counter ]
+            newest.bind(self).call(*args)
+          elsif old_method  # or call the previous incarnation of The Method
+            old_method.bind(self).call(*args)
+          else  # and if there are no older incarnations, whine about it
+            raise NoMatch.new( &quot;No functor matches the given arguments for method :#{name}.&quot; )
+          end
+        end 
+      end
+      
     end
   end
   
-  
   def initialize( &amp;block )
-    @rules = [] ; yield( self ) if block_given?
-  end
-  
-  def initialize_copy( from )
-    @rules = from.instance_eval { @rules.clone }
+    class &lt;&lt; self; include Functor::Method; end
+    yield( self ) if block_given?
   end
   
   def given( *pattern, &amp;action )
-    @rules &lt;&lt; [ pattern, action ]
+    (class &lt;&lt; self; self; end)._functor( &quot;call&quot;, false, *pattern, &amp;action)
   end
   
-  def call( *args, &amp;block )
-    match( *args, &amp;block ).call( *args )
-  end
-  
-  def []( *args, &amp;block )
-    call( *args, &amp;block )
-  end
+  def []( *args, &amp;block ); call( *args, &amp;block ); end
   
-  def to_proc ; lambda { |*args| self.call( *args ) } ; end
+  def to_proc ; lambda { |*args| call( *args ) } ; end
     
-  def match( *args, &amp;block )
-    args &lt;&lt; block if block_given?
-    pattern, action = @rules.reverse.find { | p, a | match?( args, p ) }
-    action or 
-      raise ArgumentError.new( &quot;Argument error: no functor matches the given arguments.&quot; )
-  end
-  
-  private
-  
-  def match?( args, pattern )
-    args.zip( pattern ).all? { | arg, rule | pair?( arg, rule ) } if args.length == pattern.length
-  end
-  
-  def pair?( arg, rule )
-    ( rule.respond_to? :call and rule.call( arg ) ) or rule === arg
+  def self.match?( args, pattern )
+    args.all? do |arg|
+      pat = pattern[args.index(arg)]
+      pat === arg || ( pat.respond_to?(:call) &amp;&amp; pat.call(arg))
+    end if args.length == pattern.length
   end
     
 end
\ No newline at end of file</diff>
      <filename>lib/functor.rb</filename>
    </modified>
    <modified>
      <diff>@@ -68,4 +68,4 @@ ManyArgs.new &quot;functor method&quot; do
   end
 end
 
-ManyArgs.compare_instances( 16, 32)
\ No newline at end of file
+ManyArgs.compare_instances( 4, 64)
\ No newline at end of file</diff>
      <filename>metrics/many_args.rb</filename>
    </modified>
    <modified>
      <diff>@@ -2,6 +2,8 @@ require &quot;#{here = File.dirname(__FILE__)}/helpers&quot;
 
 class A
   include Functor::Method
+  functor_cache_config :size =&gt; 700, :base =&gt; 6
+  
   functor( :foo, Integer ) { |x| :integer }
   functor( :foo, String )  { |x| :string }
   functor( :foo, Float )   { |x| :float }
@@ -24,30 +26,36 @@ class Native
 end
 
 class OneArg &lt; Steve
-  
+  before do
+    nums = (1..200).to_a
+    alphas = (&quot;a&quot;..&quot;gr&quot;).to_a
+    @args_set = nums + nums.map { |i| i.to_f } + alphas + alphas.map { |i| i.to_sym } + Array.new(200, &quot;one&quot;)
+    @args = []
+    srand(46)
+    9000.times { @args &lt;&lt; @args_set[rand(@args_set.size)] }
+  end
 end
 
-OneArg.new &quot;native method&quot; do
-  before do
-    @n = Native.new
+OneArg.new &quot;functor method&quot; do
+  before_sample do
+    @a = A.new    
   end
   measure do
-    200.times do
-      [ 1, 2, 3, 1.0, 2.0, 3.0, &quot;1&quot;, &quot;2&quot;, &quot;3&quot;, :uno, :dos, :tres, &quot;one&quot;].each { |item| @n.foo item }
-    end
+    @args.each { |item| @a.foo item }
+  end
+  
+  after_sample do
+    puts A.functor_cache[&quot;foo&quot;].map{ |c| c.size }.inspect
   end
 end
 
-OneArg.new &quot;functor method&quot; do
-  before do
-    @a = A.new
+OneArg.new &quot;native method&quot; do
+  before_sample do
+    @n = Native.new
   end
   measure do
-    200.times do
-      [ 1, 2, 1.0, 2.0, &quot;1&quot;, &quot;2&quot;, :uno, :dos, &quot;one&quot;].each { |item| @a.foo item }
-    end
+    @args.each { |item| @n.foo item }
   end
 end
 
-
-OneArg.compare_instances( 16, 32)
\ No newline at end of file
+OneArg.compare_instances( 4, 96)
\ No newline at end of file</diff>
      <filename>metrics/one_arg.rb</filename>
    </modified>
    <modified>
      <diff>@@ -2,8 +2,8 @@ require &quot;#{File.dirname(__FILE__)}/helpers&quot;
 
 fib ||= Functor.new do |f|
   f.given( Integer ) { | n | f.call( n - 1 ) + f.call( n - 2 ) }
-  f.given( 0 ) { 0 }
-  f.given( 1 ) { 1 }
+  f.given( 0 ) { |x| 0 }
+  f.given( 1 ) { |x| 1 }
 end
 
 describe &quot;Dispatch on a functor object should&quot; do</diff>
      <filename>test/fib.rb</filename>
    </modified>
    <modified>
      <diff>@@ -6,23 +6,25 @@ class Repeater
   functor( :repeat, Integer ) { |x| x * @times }
   functor( :repeat, String ) { |s| [].fill( s, 0, @times ).join(' ') }
   functor( :repeat ) { nil }
+  functor( :distraction, Integer ) { |x| &quot;Boo!&quot; }
 end
 
 describe &quot;Dispatch on instance method should&quot; do
   
   before do
     @r = Repeater.new
-    @r.times = 5
+    @r.times = 3
   end
   
   specify &quot;invoke different methods with object scope based on arguments&quot; do
-    @r.repeat( 5 ).should == 25
-    @r.repeat( &quot;-&quot; ).should == '- - - - -'
+    @r.distraction( 5 )
+    @r.repeat( 5 ).should == 15
+    @r.repeat( &quot;-&quot; ).should == '- - -'
     @r.repeat.should == nil
   end
   
   specify &quot;raise an exception if there is no matching value&quot; do
-    lambda { @r.repeat( 7.3 ) }.should.raise(ArgumentError)
+    lambda { @r.repeat( 7.3 ) }.should.raise(Functor::NoMatch)
   end
 end
 </diff>
      <filename>test/functor.rb</filename>
    </modified>
    <modified>
      <diff>@@ -4,8 +4,8 @@ describe &quot;Dispatch should support guards&quot; do
   
   before do
     @stripe = Functor.new do |f|
-      f.given( lambda { |x| x % 2 == 1 } ) { 'silver' }
-      f.given( lambda { |x| x % 2 == 0 } ) { 'white' }
+      f.given( lambda { |x| x % 2 == 1 } ) { |x| 'silver' }
+      f.given( lambda { |x| x % 2 == 0 } ) { |x| 'white' }
     end
 
     @safe_divide = Functor.new do |f|</diff>
      <filename>test/guards.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,24 +1,29 @@
 require &quot;#{File.dirname(__FILE__)}/helpers&quot;
 
-class A
+class Parent
   include Functor::Method
-  functor( :foo, Integer ) { |x| [ A, Integer ] }
-  functor( :foo, String ) { |s| [ A, String ] }
-  functor( :foo, Float ) { |h| [ A, Float ] }
+  functor( :foo, Integer ) { |x| [ Parent, Integer ] }
+  functor( :foo, String ) { |s| [ Parent, String ] }
+  functor( :foo, Float ) { |h| [ Parent, Float ] }
 end
 
-class B &lt; A
-  functor( :foo, String ) { |s| [ B, String ] }
+class Child &lt; Parent
+  functor( :foo, String ) { |s| [ Child, String ] }
+  functor( :foo, Float ) { |x| super(x).reverse }
 end
 
 describe &quot;Functor methods should support inheritance&quot; do
   
   specify &quot;by inheriting base class implementations&quot; do
-    B.new.foo( 5 ).should == [ A, Integer ]
+    Child.new.foo( 5 ).should == [ Parent, Integer ]
   end
   
   specify &quot;by allowing derived classes to override an implementation&quot; do
-    B.new.foo( &quot;bar&quot; ).should == [ B, String ]
+    Child.new.foo( &quot;bar&quot; ).should == [ Child, String ]
+  end
+  
+  specify &quot;by allowing #super&quot; do
+    Child.new.foo(3.0).should == [ Float, Parent]
   end
   
 end</diff>
      <filename>test/inheritance.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,6 +1,6 @@
 require &quot;#{File.dirname(__FILE__)}/helpers&quot;
 
-class C
+class Matchers
   include Functor::Method
   functor( :foo, Integer ) { |a| &quot;===&quot; }
   functor( :foo, 1 ) { |a| &quot;==&quot; }
@@ -10,15 +10,15 @@ end
 describe &quot;Functors match&quot; do
 
   specify &quot;using ==&quot; do
-    C.new.foo( 1 ).should == &quot;==&quot;
+    Matchers.new.foo( 1 ).should == &quot;==&quot;
   end
   
   specify &quot;using ===&quot; do
-    C.new.foo( 2 ).should == &quot;===&quot;
+    Matchers.new.foo( 2 ).should == &quot;===&quot;
   end
 
   specify &quot;using #call&quot; do
-    C.new.foo( &quot;boo&quot; ).should == &quot;Lambda: boo&quot;
+    Matchers.new.foo( &quot;boo&quot; ).should == &quot;Lambda: boo&quot;
   end
 
 end</diff>
      <filename>test/matchers.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,18 +1,18 @@
 require &quot;#{File.dirname(__FILE__)}/helpers&quot;
 
-class A
+class Reopening
   include Functor::Method
   functor( :foo, Integer ) { |x| 1 }
 end
 
-class A
+class Reopening
   functor( :foo, Integer ) { |x| 2 }
 end
 
 describe &quot;Functor methods should support reopening&quot; do
 
   specify &quot;by allowing reopening of a class to override an implementation&quot; do
-    A.new.foo( 5 ).should == 2
+    Reopening.new.foo( 5 ).should == 2
   end
 
 end</diff>
      <filename>test/reopening.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,21 +1,26 @@
 require &quot;#{File.dirname(__FILE__)}/helpers&quot;
 
-class A
+class WithSelf
   attr_accessor :bar
   include Functor::Method
   def initialize( x ) ; @bar = x ; end
   functor_with_self( :foo, self, Integer ) { |x| x }
   functor_with_self( :foo, lambda{ |x| x.bar == true }, Integer ) { |s| 'bar' }
+  functor_with_self( :foo, lambda{ |x| x.bar.is_a? String }, Integer ) { |s| 'I be string' }
 end
 
 describe &quot;Functor methods should support allow matching on self&quot; do
   
   specify &quot;by allowing functor_with_self to provide a guard on self&quot; do
-    A.new( true ).foo( 5 ).should == 'bar'
+    WithSelf.new( true ).foo( 5 ).should == 'bar'
   end
   
   specify &quot;or by simply providing self as an argument&quot; do
-    A.new( false ).foo( 5 ).should == 5
+    WithSelf.new( false ).foo( 5 ).should == 5
+  end
+  
+  specify &quot;another guard example, for those who need it&quot; do
+    WithSelf.new( &quot;me&quot; ).foo( 87 ).should == &quot;I be string&quot;
   end
 
 end</diff>
      <filename>test/with_self.rb</filename>
    </modified>
  </modified>
  <removed type="array">
    <removed>
      <filename>doc/README</filename>
    </removed>
    <removed>
      <filename>test.rb</filename>
    </removed>
  </removed>
  <parents type="array">
    <parent>
      <id>6c24edafe3b4ad4125b84b974a15df07331cc7ce</id>
    </parent>
  </parents>
  <author>
    <name>Matthew King</name>
    <email>automatthew@gmail.com</email>
  </author>
  <url>http://github.com/dyoder/functor/commit/cb65702d7fc0ef089b14f89933f06547e83a01ab</url>
  <id>cb65702d7fc0ef089b14f89933f06547e83a01ab</id>
  <committed-date>2009-02-06T15:03:41-08:00</committed-date>
  <authored-date>2009-02-06T15:00:15-08:00</authored-date>
  <message>Reworked Functor to recursively redefine its method
Fixed minor problems for compatibility with Ruby 1.9
Also added a caching system that provides a substantial speed increase</message>
  <tree>e6e4323c66cdf44a88fe35bd268f05a38f832aac</tree>
  <committer>
    <name>Matthew King</name>
    <email>automatthew@gmail.com</email>
  </committer>
</commit>
