module Defmatch

Constants

VERSION

Public Class Methods

dispatch_clone(dispatch) click to toggle source
# File lib/defmatch.rb, line 29
def self.dispatch_clone(dispatch)
  dispatch.keys.inject({}) {|nd,key| nd[key] = dispatch[key].clone; nd } if dispatch
end
inherited(klass,subklass) click to toggle source
# File lib/defmatch.rb, line 33
def self.inherited(klass,subklass)
  subklass.instance_variable_set(:@defmatch_dispatch_info,Defmatch.dispatch_clone(klass.instance_variable_get(:@defmatch_dispatch_info)))
  subklass.instance_variable_set(:@defclassmatch_dispatch_info,Defmatch.dispatch_clone(klass.instance_variable_get(:@defclassmatch_dispatch_info)))
end
signiture_match(method,args) click to toggle source
# File lib/defmatch.rb, line 3
def self.signiture_match(method,args)
  tests = args.collect do |arg|
    if arg.class == Proc
      arg
    elsif arg.class == Class
      lambda {|param| param.class == arg }
    else
      lambda {|param| param == arg }
    end
  end
  lambda do |*targs|
    if targs.size != tests.size # short circuit any testing if the airity doesn't match
      return false
    elsif targs.size > 0 # when the airity matches and there are arguments run the tests
      test = true;
      param_test_pairs = targs.zip(tests)
      param_test_pairs.each {|pair| if (pair[1].nil? or (pair[1].call(pair[0]) == false)); test = false; break; end; }
      return test
    elsif tests.size == 0 # When arguments given are empty and the tests array is empty
      return true
    else # When the arguments given are empty but the tests array is Not empty
      return false
    end
  end
end

Public Instance Methods

defclassmatch(method,*args,&block) click to toggle source

Lost of duplication between this and defmatch, but the rule is 1,2,n and we haven’t hit n

# File lib/defmatch.rb, line 65
def defclassmatch(method,*args,&block)
  @defclassmatch_dispatch_info ||= {} # setup the methods in an instance variable
  @defclassmatch_dispatch_info[method] ||= [] # setup the ordered array for the method the first time
  @defclassmatch_dispatch_info[method] << {:test => Defmatch.signiture_match(method,args), :block => block} # add the hash for the test proc and the run proc (block given) to the list of matchers

  # define dispatch method the first time
  unless respond_to?(method)
    eigenclass = class << self; self; end
    eigenclass.instance_eval do
      define_method(method) do |*args|
        self.instance_variable_get(:@defclassmatch_dispatch_info)[method].each do |hash|
          if hash[:test].call(*args)
            return self.instance_exec(*args,&hash[:block])
          end
        end
        raise ArgumentError, "No function clause matching arguments"
      end
    end
  end
end
defmatch(method,*args,&block) click to toggle source
# File lib/defmatch.rb, line 42
def defmatch(method,*args,&block)
  @defmatch_dispatch_info ||= {} # setup the methods in an instance variable
  @defmatch_dispatch_info[method] ||= [] # setup the ordered array for the method the first time
  # add the hash for the test proc and the run proc (block given) to the list of matchers
  @defmatch_dispatch_info[method] << {
    :test => Defmatch.signiture_match(method,args),
    :block => block}

  # define dispatch method the first time
  unless self.instance_methods.include?(method)
    self.send(:define_method,method) do |*args|
      self.class.instance_variable_get(:@defmatch_dispatch_info)[method].each do |hash|
        if hash[:test].call(*args)
          return self.instance_exec(*args,&hash[:block])
        end
      end
      raise ArgumentError, "No function clause matching arguments"
    end
  end

end
inherited(subklass) click to toggle source
# File lib/defmatch.rb, line 38
def inherited(subklass)
  Defmatch.inherited(self,subklass)
end