README.md in rubype-0.2.1 vs README.md in rubype-0.2.2

- old
+ new

@@ -1,62 +1,34 @@ # Ruby + Type = Rubype ```rb +# Assert class of both args is Numeric and class of return is String def sum(x, y) - x + y + (x + y).to_s end -typesig sum: [Numeric, Numeric => Numeric] -``` +typesig sum: [Numeric, Numeric => String] -This gem brings you advantage of type without changing existing code's behavior. - -Matz has mentioned Ruby3.0 with static type at some confluences. But almost all rubyists(include me) are not sure how typed Ruby is. - -But it's worth thinking more. This gem is kind of trial without so much side-effect. - -# Feature -### Typed method can coexist with non-typed method - -```ruby -# It's totally OK!! -class MyClass - def method_with_type(x, y) - x + y - end - typesig sum: [Numeric, Numeric => Numeric] - - def method_without_type(x, y) - 'string' - end +# Assert first arg has method #to_i +def sum(x, y) + x.to_i + y end +typesig sum: [:to_i, Numeric => Numeric] ``` -### Duck typing -```ruby +This gem brings you advantage of type without changing existing code's behavior. -class MyClass - def foo(any_obj) - 1 - end - typesig sum: [Any => Numeric] -end +# Feature -# It's totally OK!! -MyClass.new.foo(1) -# It's totally OK!! -MyClass.new.foo('str') -``` - ### Advantage of type * Meaningful error * Executable documentation ```rb require 'rubype' -# ex1 +# ex1: Assert class of args and return class MyClass def sum(x, y) x + y end typesig sum: [Numeric, Numeric => Numeric] @@ -69,33 +41,91 @@ MyClass.new.sum(1, 2) #=> 3 MyClass.new.sum(1, 'string') -#=> ArgumentError: Wrong type of argument, type of "str" should be Numeric +#=> Rubype::ArgumentTypeError: Expected MyClass#sum's 2th argument to be Numeric but got "string" instead MyClass.new.wrong_sum(1, 2) -#=> TypeError: Expected wrong_sum to return Numeric but got "str" instead +#=> Rubype::ReturnTypeError: Expected MyClass#wrong_sum to return Numeric but got "string" instead -# ex2 +# ex2: Assert object has specified method +class MyClass + def sum(x, y) + x.to_i + y + end + typesig sum: [:to_i, Numeric => Numeric] +end + +MyClass.new.sum('1', 2) +#=> 3 + +MyClass.new.sum(:has_no_to_i, 2) +#=> Rubype::ArgumentTypeError: Expected MyClass#sum's 1th argument to have method #to_i but got :has_no_to_i instead + + +# ex3: You can use Any class, if you want class People - type People >= Any, def marry(people) + def marry(people) # Your Ruby code as usual end + typesig marry: [People => Any] end -typesig marry: [People => Any] People.new.marry(People.new) #=> no error People.new.marry('non people') -#=> ArgumentError: Wrong type of argument, type of "non people" should be People +#=> Rubype::ArgumentTypeError: Expected People#marry's 1th argument to be People but got "non people" instead + ``` +### Typed method can coexist with non-typed method +```ruby +# It's totally OK!! +class MyClass + def method_with_type(x, y) + x + y + end + typesig sum: [Numeric, Numeric => Numeric] + def method_without_type(x, y) + 'string' + end +end +``` + +### Duck typing +You can use `Any` class. +```ruby +class MyClass + def foo(any_obj) + 1 + end + typesig foo: [Any => Numeric] + + def sum(x, y) + x.to_i + y + end + typesig sum: [:to_i, Numeric => Numeric] +end + +# It's totally OK!! +MyClass.new.foo(1) +# It's totally OK!! +MyClass.new.foo(:sym) + + +# It's totally OK!! +MyClass.new.sum(1, 2) +# It's totally OK!! +MyClass.new.sum('1', 2) +``` + + ## Installation gem install rubype or add gem 'rubype' to your Gemfile. This gem requires Ruby 2.0.0+. @@ -114,10 +144,9 @@ > 5 runs, 39 assertions, 0 failures, 0 errors, 0 skips Push to the branch (`git push origin my-new-feature`) -Create a new Pull Request +Create a new Pull Request to `develop` branch ## Credits [@chancancode](https://github.com/chancancode) and [This article](http://blog.codeclimate.com/blog/2014/05/06/gradual-type-checking-for-ruby/) first brought this to my attention. I've stolen some idea from them. -