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
|