Module: MultiMethods::ClassMethods

Defined in:
lib/multi_methods.rb

Instance Method Summary collapse

Instance Method Details

#create_method(name, &block) ⇒ Object



9
10
11
# File 'lib/multi_methods.rb', line 9

def create_method( name, &block ) 
  self.send( :define_method, name, block )
end

#defmethod(method_name, dispatch_value, default_dispatch_fn) ⇒ Object



44
45
46
47
48
# File 'lib/multi_methods.rb', line 44

def defmethod method_name, dispatch_value, default_dispatch_fn
  multi_method = self.instance_variable_get( "@" + method_name.to_s)  
  raise "MultiMethod #{method_name} not defined" unless  multi_method
  multi_method << {  dispatch_value => default_dispatch_fn } 
end

#defmulti(method_name, default_dispatch_fn = nil) ⇒ Object



13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/multi_methods.rb', line 13

def defmulti method_name, default_dispatch_fn = nil
  self.instance_variable_set( "@" + method_name.to_s, [] )

  create_method( method_name ) do |*args|
    dispatch_table = self.class.instance_variable_get( "@" + method_name.to_s )

    dispatch_table.each do |m|
      predicate = if m.keys.first.respond_to? :call
                    raise "Dispatch method already defined by defmulti" if default_dispatch_fn
                    m.keys.first
                  elsif  m.keys.first == :default
                    :default
                  else
                    lambda { |args| return default_dispatch_fn.call(args) == m.keys.first }
                  end

      destination_fn = m.values.first

      if predicate == :default  || predicate.call(args)
        if destination_fn.is_a? UnboundMethod
          break destination_fn.bind( self ).call(args)
        else
          break destination_fn.call(args)
        end
        break
      end
      raise "No matching dispatcher function found" if dispatch_table.last == m
    end
  end
end