rubype 0.2.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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