Create multimethods in Ruby
Add this line to Gemfile:
gem 'ov'
Execute:
$ bundle
Or install it yourself as:
$ gem install ov
require 'ov'
# ====== Define methods
class Foo
include Ov
let :foo, String do |str|
# some code
end
end
foo = Foo.new
foo.foo("foo") # => ok
foo.foo(123) # => Method `foo` in `#<Foo:0x007fe423c19dc8>` class with types `Fixnum` not implemented. (Ov::NotImplementError)
# ====== Custom Equality for Ruby Types
class String
include Ov
let :is_equal, String do |str|
self == str
end
let :is_equal, Any do |other|
raise TypeError.new("Only for string")
end
end
str = "foo"
p str == 123 # false, but this different types
p str.is_equal("bar") # false
p str.is_equal("foo") # true
p str.is_equal(123) # TypeError
# ====== Use Ov::Ext for matching
require 'kleisli'
include Ov::Ext
match(Try{1/0}) {
try(Kleisli::Try::Success) { puts "ok" }
try(Kleisli::Try::Failure) { puts "error" }
}
result = match(Net::HTTP.get_response(URI("http://google.com"))) do
try(Net::HTTPOK) {|r| r.header }
try(Net::HTTPMovedPermanently) {|r| r.header }
otherwise { "error" }
end
puts result
Firstly include Ov
in your class
class MyClass
include Ov
end
After: define method with types:
class MyClass
include Ov
#with Fixnum type
let :cool_method, Fixnum do |num|
num * 100
end
#with String type
let :cool_method, String do |str|
str << "!"
end
end
#And now
my_class = MyClass.new
my_class.cool_method(3) # => 300
my_class.cool_method("foo") # => foo!
class MyClass
self << class
let :cool_method, Fixnum do |f|
f + 1
end
let :cool_method, String do |s|
"{s}"
end
end
end
MyClass.cool_method(1) #=> 2
MyClass.cool_method("test") #=> "test"
class MyClass
include Ov
let :cool_method, Any do |any|
any
end
end
my_class = MyClass.new
my_class.cool_method(1) => 1
my_class.cool_method("foo") => "foo"
Redefine methods
class A
def test(str)
p "A#test"
end
end
class B < A
include Ov
let :test, Fixnum do |num|
p "only for fixnum"
end
end
b = B.new
b.test("asd") # => A#test
b.test(123) # => only for fixnum
Call method:
class A
include Ov
let :test, Fixnum do |num|
test("#{num}") # call with string argument
end
let :test, String do |str|
p str
end
end
a = A.new
a.test(123) # => "123"
Work with blocks
class MyClass
include Ov
let :my_method, Fixnum do |num, block| # instead of |num, &block|
p num
block.call
end
end
MyClass.new.my_method(1) do
p "123"
end
# => 1
# => 123
see link
- work with symbol method names:
+, -, *, etc
- some ideas
# multiple arguments
let :test, Integer, [String] # signature: Integer, and others must be String
let :test, Multiple #any types
let :test, :foo # Type must have :foo method
let :test, Or[Integer, String] # work for String or Integer
- Fork it
- Create your feature branch (
git checkout -b my-new-feature
) - Commit your changes (
git commit -am 'Add some feature'
) - Push to the branch (
git push origin my-new-feature
) - Create new Pull Request