rubype 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (5) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +50 -34
  3. data/lib/rubype.rb +14 -4
  4. data/lib/rubype/version.rb +1 -1
  5. metadata +1 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6c7e1779556b1e9829b3b5043bc96aba5caaacb1
4
- data.tar.gz: b2c48bd090e006e27a176803c0833d3a39883226
3
+ metadata.gz: 5a1d6b7168106e0de86c7111cfe41bfe191a4217
4
+ data.tar.gz: 2663b2cfef26e3eb90ee0c0932be7d34bb562ddb
5
5
  SHA512:
6
- metadata.gz: 165eeb9c15017ab93dfefcf66236ff8096274bbd65e87fa082e0ae0fd62c10712c6636085fdd46dc96d06a59b1ddf318f9e97dcacd7df7bb78052441459bbcd6
7
- data.tar.gz: 5983be0188e80c963ce8994949ff461abc99ea9217e8cde4265c088b2c4f565b58ee4146762e29a2ed76ac8b098436b3203c0b7caef1f7b4fea2be74ad45f2b9
6
+ metadata.gz: 0dce04b7c97e12030468f044af562c51c04446ed033d17acd27da10355dae3751a0fd8bc74dc8c15e8cdde31d0c6d9710d420a2cf106c6a36495636ac4a9a20e
7
+ data.tar.gz: 85d34a6e01587cab72001f08f13ca372c39a72efdb52b6b3506b10b12b7de0582f4087a60b8d23929ecb6454921a74e26edf1b0760607493083f40906b355e0f
data/README.md CHANGED
@@ -1,9 +1,56 @@
1
- # Ruby with Type.
1
+ # Ruby + Type = Rubype
2
+
3
+ ```rb
4
+ def sum(x, y)
5
+ x + y
6
+ end
7
+ typesig sum: [Numeric, Numeric => Numeric]
8
+ ```
9
+
10
+ This gem brings you advantage of type without changing existing code's behavior.
2
11
 
3
12
  Matz has mentioned Ruby3.0 with static type at some confluences. But almost all rubyists(include me) are not sure how typed Ruby is.
4
13
 
5
14
  But it's worth thinking more. This gem is kind of trial without so much side-effect.
6
15
 
16
+ # Feature
17
+ ### Typed method can coexist with non-typed method
18
+
19
+ ```ruby
20
+ # It's totally OK!!
21
+ class MyClass
22
+ def method_with_type(x, y)
23
+ x + y
24
+ end
25
+ typesig sum: [Numeric, Numeric => Numeric]
26
+
27
+ def method_without_type(x, y)
28
+ 'string'
29
+ end
30
+ end
31
+ ```
32
+
33
+ ### Duck typing
34
+
35
+ ```ruby
36
+
37
+ class MyClass
38
+ def foo(any_obj)
39
+ 1
40
+ end
41
+ typesig sum: [Any => Numeric]
42
+ end
43
+
44
+ # It's totally OK!!
45
+ MyClass.new.foo(1)
46
+ # It's totally OK!!
47
+ MyClass.new.foo('str')
48
+ ```
49
+
50
+ ### Advantage of type
51
+ * Meaningful error
52
+ * Executable documentation
53
+
7
54
  ```rb
8
55
  require 'rubype'
9
56
 
@@ -45,39 +92,7 @@ People.new.marry('non people')
45
92
  #=> ArgumentError: Wrong type of argument, type of "non people" should be People
46
93
  ```
47
94
 
48
- ## Feature
49
- ### Typed method can coexist with non-typed method
50
-
51
- ```ruby
52
- # It's totally OK!!
53
- class MyClass
54
- def sum(x, y)
55
- x + y
56
- end
57
- typesig sum: [Numeric, Numeric => Numeric]
58
-
59
- def sum_without_type(x, y)
60
- 'string'
61
- end
62
- end
63
- ```
64
-
65
- ### Duck typing
66
95
 
67
- ```ruby
68
-
69
- class MyClass
70
- def foo(any_obj)
71
- 1
72
- end
73
- typesig sum: [Any => Numeric]
74
- end
75
-
76
- # It's totally OK!!
77
- MyClass.new.foo(1)
78
- # It's totally OK!!
79
- MyClass.new.foo('str')
80
- ```
81
96
 
82
97
  ## Installation
83
98
 
@@ -104,4 +119,5 @@ Push to the branch (`git push origin my-new-feature`)
104
119
  Create a new Pull Request
105
120
 
106
121
  ## Credits
107
- [@chancancode](https://github.com/chancancode) first brought this to my attention. I've stolen some idea from him.
122
+ [@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.
123
+
data/lib/rubype.rb CHANGED
@@ -1,5 +1,3 @@
1
- require "rubype/rubype"
2
-
3
1
  # Builtin Contracts
4
2
  class Any; end
5
3
  module Boolean; end
@@ -13,14 +11,15 @@ class Module
13
11
  @__rubype__
14
12
  end
15
13
 
14
+ # @param hash [Hash] {method_name: [ArgClass1, ArgClass2, ... ArgClassn => RtnClass]}
16
15
  def typesig(hash)
17
16
  meth = hash.keys.first
18
17
  *arg_types, type_pair = hash.values.first
19
18
 
20
19
  __rubype__.send(:define_method, meth) do |*args, &block|
21
- ::Rubype.assert_arg_type(meth, args, arg_types << type_pair.keys.first)
20
+ ::Rubype.send(:assert_arg_type, meth, args, arg_types << type_pair.keys.first)
22
21
  rtn = super(*args, &block)
23
- ::Rubype.assert_trn_type(meth, rtn, type_pair.values.first)
22
+ ::Rubype.send(:assert_trn_type, meth, rtn, type_pair.values.first)
24
23
  rtn
25
24
  end
26
25
  self
@@ -29,6 +28,11 @@ end
29
28
 
30
29
  module Rubype
31
30
  class << self
31
+ private
32
+
33
+ # @param meth [Symbol]
34
+ # @param args [Array<Object>]
35
+ # @param klasses [Array<Class>]
32
36
  def assert_arg_type(meth, args, klasses)
33
37
  args.each_with_index do |arg, i|
34
38
  if wrong_type?(arg, klasses[i])
@@ -37,12 +41,18 @@ module Rubype
37
41
  end
38
42
  end
39
43
 
44
+ # @param meth [Symbol]
45
+ # @param rtn [Object]
46
+ # @param klass [Class]
40
47
  def assert_trn_type(meth, rtn, klass)
41
48
  if wrong_type?(rtn, klass)
42
49
  raise TypeError, "Expected #{meth} to return #{klass} but got #{rtn.inspect} instead"
43
50
  end
44
51
  end
45
52
 
53
+ # @param obj [Object]
54
+ # @param klass [Class]
55
+ # @return [Boolean]
46
56
  def wrong_type?(obj, klass)
47
57
  !(obj.is_a?(klass) || klass == Any)
48
58
  end
@@ -1,3 +1,3 @@
1
1
  module Rubype
2
- VERSION = "0.2.0"
2
+ VERSION = "0.2.1"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubype
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - gogotanaka