Add mutlti dispatch functionality to Ruby
Ruby
Switch branches/tags
Nothing to show
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
lib
spec
.gitignore
.travis.yml
Gemfile
LICENSE.txt
README.rdoc
Rakefile
multidispatch_dsl.gemspec

README.rdoc

MultidispatchDSL

If you worked with other languages you probably know multi dispatch feature - define variants of same method with different number of arguments of different types. In Ruby with it's duck typing you can't do it from out of box. This gem will allow you to do it.

Build Status Gem Version

Installation

Add this line to your application's Gemfile:

gem 'multidispatch_dsl'

And then execute:

$ bundle

Or install it yourself as:

$ gem install multidispatch_dsl

Usage

Just include MultidispatchDSL into your class and your will get `mdef` class method. For example

class TestClass
  include MultidispatchDSL

  # hello method with one integer argument
  mdef(:hello, Fixnum) do |i|
    "Fixnum version with number #{ i }"
  end

  # hello method with one string argument
  mdef(:hello, String) do |str|
    "String version with string #{ str }"
  end

  # hello method with fixnum and string arguments
  mdef(:hello, Fixnum, String) do |i, str|
    "Fixnum String version with #{ i } & #{ str }"
  end

  # hello method with string and fixnum arguments
  mdef(:hello, String, Fixnum) do |str, i|
    "String Fixnum version with #{ str } & #{ i }"
  end

  # hello method without arguments
  mdef(:hello) do
    "Version without args"
  end

  # hello method with symbol argument
  mdef(:hello, Symbol) do |symbol|
    "Symbol version with :#{ symbol } & :#{ internal_method }"
  end

  # hello method with 2 string argument and nested block
  mdef(:hello, String, String) do |str_one, str_two, &block|
    instance_exec(str_one.upcase, str_two.downcase, &block)
  end

  def internal_method
    :internal_method
  end
end

test_instance = TestClass.new

test_instance.hello
#=> "Version without args"

test_instance.hello(1)
#=> "Fixnum version with number 1"

test_instance.hello(:foo)
#=> "Symbol version with :foo & :internal_method"

test_instance.hello(1, "string")
#=> "Fixnum String version with 1 & string"

test_instance.hello("string", 1)
#=> "String Fixnum version with string & 1"

test_instance.hello(:not, :defined)
#=> raise error MultidispatchDSL::MissingDeclarationError

test_instance.hello('One', 'Two') { |str_one, str_two| "#{str_one} #{ str_two } #{ internal_method }" }
#=> "ONE two internal_method"

As you can see defining version of method with yield is little bit tricky. That because defining method from block add extra scope. More details about it here www.andylindeman.com/2011/01/08/defining-methods-using-blocks-in-ruby.html

If you need define version of method for any number arguments of any types use `:anything` symbol

mdef(:process, String) do |value|
  { :string => value }
end

mdef(:process, Fixnum) do |value|
  { :int => value }
end

mdef(:process, :anything) do |value|
  { :anything => value }
end

If you desire add this functionality to all classes just include MultidispatchDSL to Object class:

Object.send(:include, MultidispatchDSL)

Requirements

Ruby >= 1.9.2 and other ruby implementations with 1.9 mode

Contributing

  1. Fork it

  2. Create your feature branch (`git checkout -b my-new-feature`)

  3. Commit your changes (`git commit -am 'Add some feature'`)

  4. Push to the branch (`git push origin my-new-feature`)

  5. Create new Pull Request