Method: Object#defpattern
- Defined in:
- lib/funtools/pattern-matching.rb
#defpattern(sym) ⇒ Object
Public: Define a method in the current scope which allow pattern matching function declaration to be used.
sym - Symbol defining the name of the method to be created. block - Block containing the logic for the function to be created.
Returns nothing.
9 10 11 12 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 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
# File 'lib/funtools/pattern-matching.rb', line 9 def defpattern(sym) match = ->(a, b) do if([a,b].map { |o| o.is_a?(Enumerable) && a.class == b.class }.all?) raise ArgumentError unless a.length == b.length zipped = a.is_a?(Hash) ? a.sort.zip(b.sort) : a.zip(b) zipped.reduce(true) do |c, e| c && match.(*e) end else a.nil? || a == b end end old_method = self.class.method(sym) if self.class.method_defined?(:sym) patterns = [] self.class.send(:define_method, sym) do |*l, &b| patterns << ->(*n) do ->(*m) do if m.length == n.length e = m.zip(n) raise NoMatch if e.reject { |e| match.(*e) }.any? instance_exec(*n, &b) end end.(*l) end end yield if old_method self.class.send(:define_method, sym, &old_method) else self.class.send(:remove_method, sym) end = :define_method if respond_to?(:define_method, true) ||= :define_singleton_method self.send(, sym) do |*args| patterns.each do |pattern| begin return instance_exec(*args, &pattern) rescue NoMatch end end instance_exec { raise NoMatch } end end |