rtype-legacy-java 0.0.4-java
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.
- checksums.yaml +7 -0
- data/Gemfile +3 -0
- data/LICENSE +9 -0
- data/README.md +475 -0
- data/Rakefile +12 -0
- data/benchmark/benchmark.rb +104 -0
- data/ext/rtype/legacy/rtype_legacy_java.jar +0 -0
- data/spec/rtype_legacy_spec.rb +971 -0
- data/spec/spec_helper.rb +14 -0
- metadata +97 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 78d88663795698815c19fe35507f697dfb2ebd0f
|
4
|
+
data.tar.gz: e9d2e61a7a944a248c48786635d18fec18995d2f
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: fae5879fc185a5d7de087492e2230729c326bbbeee950c371c7448b74b9e863daa8402e0cc42a940e92f672c4e74d3d5656e751cb7fdeb4d21b2689105a3800e
|
7
|
+
data.tar.gz: 750ad92ad7a462ccba10250091b2f7c75474d8642810daf92f0176c6a6f3fd8af2742dce3cdebc8de973cac5704c18e4a66d40574b16230d5d9f5ffa1ce87af2
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2016 Sputnik Gugja
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
6
|
+
|
7
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
8
|
+
|
9
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,475 @@
|
|
1
|
+
# Rtype Legacy: ruby with type (rtype for ruby 1.9+)
|
2
|
+
[](https://badge.fury.io/rb/rtype-legacy)
|
3
|
+
[](https://travis-ci.org/sputnikgugja/rtype-legacy)
|
4
|
+
[](https://coveralls.io/github/sputnikgugja/rtype-legacy?branch=master)
|
5
|
+
|
6
|
+
```ruby
|
7
|
+
require 'rtype/legacy'
|
8
|
+
|
9
|
+
class Test
|
10
|
+
rtype [:to_i, Numeric] => Numeric
|
11
|
+
def sum(a, b)
|
12
|
+
a.to_i + b
|
13
|
+
end
|
14
|
+
|
15
|
+
# Second hash is keyword argument signature
|
16
|
+
# (syntax compatibility with 'rtype' gem)
|
17
|
+
rtype [{state: Boolean}, {}] => Boolean
|
18
|
+
def self.invert(opts)
|
19
|
+
!opts[:state]
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
Test.new.sum(123, "asd")
|
24
|
+
# (Rtype::ArgumentTypeError) for 2nd argument:
|
25
|
+
# Expected "asd" to be a Numeric
|
26
|
+
|
27
|
+
Test.invert(state: 0)
|
28
|
+
# (Rtype::ArgumentTypeError) for 1st argument:
|
29
|
+
# Expected {:state=>0} to be a hash with 1 elements:
|
30
|
+
# - state : Expected 0 to be a Boolean
|
31
|
+
```
|
32
|
+
|
33
|
+
## Requirements
|
34
|
+
- Ruby >= 1.9
|
35
|
+
- If you are using ruby 2.1+, see [rtype](https://github.com/sputnikgugja/rtype)
|
36
|
+
- MRI
|
37
|
+
- If C native extension is used. otherwise it is not required
|
38
|
+
- JRuby (JRuby 1.7+)
|
39
|
+
- If Java extension is used. otherwise it is not required
|
40
|
+
|
41
|
+
## Difference between rtype and rtype-legacy
|
42
|
+
- The two are separate gem
|
43
|
+
- Rtype requires ruby 2.1+. Rtype Legacy requires ruby 1.9+
|
44
|
+
- Rtype supports 'type checking for keyword argument'. Rtype Legacy doesn't
|
45
|
+
- Rtype uses `Module#prepend`. Rtype Legacy redefines method
|
46
|
+
- Rtype can be used outside of module (with specifying method name). Rtype Legacy can't be used outside of module
|
47
|
+
|
48
|
+
## Features
|
49
|
+
- Provides type checking for arguments and return
|
50
|
+
- [Type checking for hash elements](#hash)
|
51
|
+
- [Duck Typing](#duck-typing)
|
52
|
+
- [Typed Array](#typed-array), Typed Set, Typed Hash
|
53
|
+
- [Numeric check](#special-behaviors). e.g. `Int >= 0`
|
54
|
+
- [Type checking for getter and setter](#attr_accessor-with-rtype)
|
55
|
+
- [float_accessor](#float_accessor), [bool_accessor](#bool_accessor)
|
56
|
+
- Custom type behavior
|
57
|
+
- ...
|
58
|
+
|
59
|
+
## Installation
|
60
|
+
Run `gem install rtype-legacy` or add `gem 'rtype-legacy'` to your `Gemfile`
|
61
|
+
|
62
|
+
And add to your `.rb` source file:
|
63
|
+
```ruby
|
64
|
+
require 'rtype/legacy'
|
65
|
+
```
|
66
|
+
|
67
|
+
### Native extension
|
68
|
+
Rtype itself is pure-ruby gem. but you can make it more faster by using native extension.
|
69
|
+
|
70
|
+
#### Native extension for MRI
|
71
|
+
Run
|
72
|
+
```ruby
|
73
|
+
gem install rtype-legacy-native
|
74
|
+
```
|
75
|
+
or add to your `Gemfile`:
|
76
|
+
```ruby
|
77
|
+
gem 'rtype-legacy-native'
|
78
|
+
```
|
79
|
+
then, Rtype Legacy uses it. (**Do not** `require 'rtype-legacy-native'`)
|
80
|
+
|
81
|
+
#### Java extension for JRuby is automatic
|
82
|
+
**Do not** `require 'rtype-java'`
|
83
|
+
|
84
|
+
## Usage
|
85
|
+
|
86
|
+
### Supported Type Behaviors
|
87
|
+
- `Module` : Value must be of this module (`is_a?`)
|
88
|
+
- `Any` : Alias for `BasicObject` (means Any Object)
|
89
|
+
- `Boolean` : `true` or `false`
|
90
|
+
- `Symbol` : Value must respond to a method with this name
|
91
|
+
- `Regexp` : Value must match this regexp pattern
|
92
|
+
- `Range` : Value must be included in this range
|
93
|
+
- `Array` : Value can be any type in this array
|
94
|
+
- `Proc` : Value must return a truthy value for this proc
|
95
|
+
- `true` : Value must be truthy
|
96
|
+
- `false` : Value must be falsy
|
97
|
+
- `nil` : Value must be nil
|
98
|
+
- `Hash`
|
99
|
+
- Value must be a hash
|
100
|
+
- Each of elements must be valid
|
101
|
+
- Keys of the value must be equal to keys of this hash
|
102
|
+
- **String** key is **different** from **symbol** key
|
103
|
+
- vs. Keyword arguments (e.g.)
|
104
|
+
- `[{}]` is **not** hash argument. it is keyword argument, because its position is last
|
105
|
+
- `[{}, {}]` is hash argument (first) and keyword argument (second)
|
106
|
+
- `[{}, {}, {}]` is two hash argument (first, second) and keyword argument (last)
|
107
|
+
- `{}` is keyword argument. non-keyword arguments must be in array.
|
108
|
+
- Of course, nested hash works
|
109
|
+
- Example: [Hash](#hash)
|
110
|
+
|
111
|
+
- [Special Behaviors](#special-behaviors)
|
112
|
+
- `TypedArray, TypedSet, TypedHash`, `Num, Int, Flo`, `And`, `Xor`, `Not`, `Nilable`
|
113
|
+
|
114
|
+
### Examples
|
115
|
+
|
116
|
+
#### Basic
|
117
|
+
```ruby
|
118
|
+
require 'rtype'
|
119
|
+
|
120
|
+
class Example
|
121
|
+
rtype [Integer] => nil
|
122
|
+
def test(i)
|
123
|
+
end
|
124
|
+
|
125
|
+
rtype [Any] => nil
|
126
|
+
def any_type_arg(arg)
|
127
|
+
end
|
128
|
+
|
129
|
+
rtype [] => Integer
|
130
|
+
def return_type_test
|
131
|
+
"not integer"
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
e = Example.new
|
136
|
+
e.test("not integer")
|
137
|
+
# (Rtype::ArgumentTypeError) for 1st argument:
|
138
|
+
# Expected "not integer" to be a Integer
|
139
|
+
|
140
|
+
e.any_type_arg("Any argument!") # Works
|
141
|
+
|
142
|
+
e.return_type_test
|
143
|
+
# (Rtype::ReturnTypeError) for return:
|
144
|
+
# Expected "not integer" to be a Integer
|
145
|
+
```
|
146
|
+
|
147
|
+
#### Duck typing
|
148
|
+
```ruby
|
149
|
+
require 'rtype'
|
150
|
+
|
151
|
+
class Duck
|
152
|
+
rtype [:to_i] => Any
|
153
|
+
def says(i)
|
154
|
+
puts "duck:" + " quack"*i.to_i
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
Duck.new.says("2") # duck: quack quack
|
159
|
+
```
|
160
|
+
|
161
|
+
#### Array
|
162
|
+
```ruby
|
163
|
+
rtype :ruby!, [[String, Integer]] => Any
|
164
|
+
def ruby!(arg)
|
165
|
+
puts "ruby!"
|
166
|
+
end
|
167
|
+
|
168
|
+
func("str") # ruby!
|
169
|
+
func(123) # ruby!
|
170
|
+
|
171
|
+
func(nil)
|
172
|
+
# (Rtype::ArgumentTypeError) for 1st argument:
|
173
|
+
# Expected nil to be a String
|
174
|
+
# OR Expected nil to be a Integer
|
175
|
+
```
|
176
|
+
|
177
|
+
#### Hash
|
178
|
+
```ruby
|
179
|
+
# last hash element is keyword arguments
|
180
|
+
rtype :func, [{msg: String}, {}] => Any
|
181
|
+
def func(hash)
|
182
|
+
puts hash[:msg]
|
183
|
+
end
|
184
|
+
|
185
|
+
func({})
|
186
|
+
# (Rtype::ArgumentTypeError) for 1st argument:
|
187
|
+
# Expected {} to be a hash with 1 elements:
|
188
|
+
# - msg : Expected nil to be a String
|
189
|
+
|
190
|
+
func({msg: 123})
|
191
|
+
# (Rtype::ArgumentTypeError) for 1st argument:
|
192
|
+
# Expected {:msg=>123} to be a hash with 1 elements:
|
193
|
+
# - msg : Expected 123 to be a String
|
194
|
+
|
195
|
+
func({msg: "hello", key: 'value'})
|
196
|
+
# (Rtype::ArgumentTypeError) for 1st argument:
|
197
|
+
# Expected {:msg=>"hello", :key=>"value"} to be a hash with 1 elements:
|
198
|
+
# - msg : Expected "hello" to be a String
|
199
|
+
|
200
|
+
func({"msg" => "hello hash"})
|
201
|
+
# (Rtype::ArgumentTypeError) for 1st argument:
|
202
|
+
# Expected {"msg"=>"hello hash"} to be a hash with 1 elements:
|
203
|
+
# - msg : Expected nil to be a String
|
204
|
+
|
205
|
+
func({msg: "hello hash"}) # hello hash
|
206
|
+
```
|
207
|
+
|
208
|
+
#### attr_accessor with rtype
|
209
|
+
- `rtype_accessor(*names, type)` : calls `attr_accessor` if the accessor methods(getter/setter) are not defined. and makes it typed
|
210
|
+
- `rtype_reader(*names, type)` : calls `attr_reader` if the getters are not defined. and makes it typed
|
211
|
+
- `rtype_writer(*names, type)` : calls `attr_writer` if the setters are not defined. and makes it typed
|
212
|
+
|
213
|
+
You can use `rtype_accessor_self` for static accessor. (`rtype_reader_self`, `rtype_writer_self` also exist)
|
214
|
+
|
215
|
+
```ruby
|
216
|
+
require 'rtype'
|
217
|
+
|
218
|
+
class Example
|
219
|
+
rtype_accessor :value, String
|
220
|
+
|
221
|
+
def initialize
|
222
|
+
@value = 456
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
Example.new.value = 123
|
227
|
+
# (Rtype::ArgumentTypeError) for 1st argument:
|
228
|
+
# Expected 123 to be a String
|
229
|
+
|
230
|
+
Example.new.value
|
231
|
+
# (Rtype::ReturnTypeError) for return:
|
232
|
+
# Expected 456 to be a String
|
233
|
+
```
|
234
|
+
|
235
|
+
#### Typed Array
|
236
|
+
```ruby
|
237
|
+
### TEST 1 ###
|
238
|
+
class Test
|
239
|
+
rtype [Array.of(Integer)] => Any
|
240
|
+
def sum(args)
|
241
|
+
num = 0
|
242
|
+
args.each { |e| num += e }
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
sum([1, 2, 3]) # => 6
|
247
|
+
|
248
|
+
sum([1.0, 2, 3])
|
249
|
+
# (Rtype::ArgumentTypeError) for 1st argument:
|
250
|
+
# Expected [1.0, 2, 3] to be an array with type Integer"
|
251
|
+
```
|
252
|
+
|
253
|
+
```ruby
|
254
|
+
### TEST 2 ###
|
255
|
+
class Test
|
256
|
+
rtype [ Array.of([Integer, Float]) ] => Any
|
257
|
+
def sum(args)
|
258
|
+
num = 0
|
259
|
+
args.each { |e| num += e }
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
sum([1, 2, 3]) # => 6
|
264
|
+
sum([1.0, 2, 3]) # => 6.0
|
265
|
+
```
|
266
|
+
|
267
|
+
#### float_accessor
|
268
|
+
```ruby
|
269
|
+
class Point
|
270
|
+
float_accessor :x, :y
|
271
|
+
end
|
272
|
+
|
273
|
+
v = Point.new
|
274
|
+
v.x = 1
|
275
|
+
v.x # => 1.0 (always Float)
|
276
|
+
```
|
277
|
+
|
278
|
+
#### bool_accessor
|
279
|
+
```ruby
|
280
|
+
class Human
|
281
|
+
bool_accessor :hungry
|
282
|
+
end
|
283
|
+
|
284
|
+
a = Human.new
|
285
|
+
a.hungry = true
|
286
|
+
a.hungry? # => true
|
287
|
+
a.hungry # NoMethodError
|
288
|
+
```
|
289
|
+
|
290
|
+
#### `rtype`
|
291
|
+
```ruby
|
292
|
+
require 'rtype'
|
293
|
+
|
294
|
+
class Example
|
295
|
+
# Recommended. With annotation mode (no method name required)
|
296
|
+
rtype [Integer, String] => String
|
297
|
+
def hello_world(i, str)
|
298
|
+
puts "Hello? #{i} #{st
|
299
|
+
end
|
300
|
+
|
301
|
+
# Works (with specifying method name)
|
302
|
+
rtype :hello_world, [Integer, String] => String
|
303
|
+
def hello_world(i, str)
|
304
|
+
puts "Hello? #{i} #{st
|
305
|
+
end
|
306
|
+
|
307
|
+
# Works
|
308
|
+
def hello_world_two(i, str)
|
309
|
+
puts "Hello? #{i} #{str}"
|
310
|
+
end
|
311
|
+
rtype :hello_world_two, [Integer, String] => String
|
312
|
+
|
313
|
+
# Also works (String will be converted to Symbol)
|
314
|
+
rtype 'hello_world_three', [Integer, String] => String
|
315
|
+
def hello_world_three(i, str)
|
316
|
+
puts "Hello? #{i} #{str}"
|
317
|
+
end
|
318
|
+
|
319
|
+
# Doesn't work. annotation mode works for following (next) method
|
320
|
+
def hello_world_four(i, str)
|
321
|
+
puts "Hello? #{i} #{str}"
|
322
|
+
end
|
323
|
+
rtype [Integer, String] => String
|
324
|
+
end
|
325
|
+
```
|
326
|
+
|
327
|
+
#### Class method
|
328
|
+
Annotation mode works for both instance method and class method
|
329
|
+
|
330
|
+
```ruby
|
331
|
+
require 'rtype'
|
332
|
+
|
333
|
+
class Example
|
334
|
+
rtype [:to_i] => Any
|
335
|
+
def self.say_ya(i)
|
336
|
+
puts "say" + " ya"*i.to_i
|
337
|
+
end
|
338
|
+
end
|
339
|
+
|
340
|
+
Example::say_ya(3) #say ya ya ya
|
341
|
+
```
|
342
|
+
|
343
|
+
if you specify method name, however, you must use `rtype_self` instead of `rtype`
|
344
|
+
|
345
|
+
```ruby
|
346
|
+
require 'rtype'
|
347
|
+
|
348
|
+
class Example
|
349
|
+
rtype_self :say_ya, [:to_i] => Any
|
350
|
+
def self.say_ya(i)
|
351
|
+
puts "say" + " ya"*i.to_i
|
352
|
+
end
|
353
|
+
end
|
354
|
+
|
355
|
+
Example::say_ya(3) #say ya ya ya
|
356
|
+
```
|
357
|
+
|
358
|
+
#### Type information
|
359
|
+
This is just 'information'
|
360
|
+
|
361
|
+
Any change of this doesn't affect type checking
|
362
|
+
|
363
|
+
```ruby
|
364
|
+
require 'rtype'
|
365
|
+
|
366
|
+
class Example
|
367
|
+
rtype [:to_i] => Any
|
368
|
+
def test(i)
|
369
|
+
end
|
370
|
+
end
|
371
|
+
|
372
|
+
Example.new.method(:test).type_info
|
373
|
+
# => [:to_i] => Any
|
374
|
+
Example.new.method(:test).argument_type
|
375
|
+
# => [:to_i]
|
376
|
+
Example.new.method(:test).return_type
|
377
|
+
# => Any
|
378
|
+
```
|
379
|
+
|
380
|
+
#### Special Behaviors
|
381
|
+
- `TypedArray` : Ensures value is an array with the type (type signature)
|
382
|
+
- `Array.of(type)` (recommended)
|
383
|
+
- Example: [TypedArray](#typed-array)
|
384
|
+
|
385
|
+
- `TypedSet` : Ensures value is a set with the type (type signature)
|
386
|
+
- `Set.of(type)` (recommended)
|
387
|
+
|
388
|
+
- `TypedHash` : Ensures value is a hash with the type (type signature)
|
389
|
+
- `Hash.of(key_type, value_type)` (recommended)
|
390
|
+
|
391
|
+
- `Num, Int, Flo` : Numeric check
|
392
|
+
- `Num/Int/Flo >/>=/</<=/== x`
|
393
|
+
- e.g. `Num >= 2` means value must be a `Numeric` and >= 2
|
394
|
+
- e.g. `Int >= 2` means value must be a `Integer` and >= 2
|
395
|
+
- e.g. `Flo >= 2` means value must be a `Float` and >= 2
|
396
|
+
|
397
|
+
- `And` : Ensures value is valid for all given types
|
398
|
+
- `Rtype.and(*types)`, `Rtype::Behavior::And[*types]`
|
399
|
+
- or `Array#comb`, `Object#and(*others)`
|
400
|
+
|
401
|
+
- `Xor` : Ensures value is valid for only one of given types
|
402
|
+
- `Rtype.xor(*types)`, `Rtype::Behavior::Xor[*types]`
|
403
|
+
- or `Object#xor(*others)`
|
404
|
+
|
405
|
+
- `Not` : Ensures value is not valid for all given types
|
406
|
+
- `Rtype.not(*types)`, `Rtype::Behavior::Not[*types]`
|
407
|
+
- or `Object#not`
|
408
|
+
|
409
|
+
- `Nilable` : Value can be nil
|
410
|
+
- `Rtype.nilable(type)`, `Rtype::Behavior::Nilable[type]`
|
411
|
+
- or `Object#nilable`, `Object#or_nil`
|
412
|
+
|
413
|
+
- You can create custom behaviors by extending `Rtype::Behavior::Base`
|
414
|
+
|
415
|
+
## Documentation
|
416
|
+
[RubyDoc.info](http://www.rubydoc.info/gems/rtype-legacy)
|
417
|
+
|
418
|
+
## Benchmarks
|
419
|
+
Result of `rake benchmark` ([source](https://github.com/sputnikgugja/rtype-legacy/tree/master/benchmark/benchmark.rb))
|
420
|
+
|
421
|
+
Rubype and Sig don't support 1.9 ruby. Typecheck raises an error in my environment
|
422
|
+
|
423
|
+
### MRI
|
424
|
+
```
|
425
|
+
Ruby version: 1.9.3
|
426
|
+
Ruby engine: ruby
|
427
|
+
Ruby description: ruby 1.9.3p551 (2014-11-13 revision 48407) [i686-linux]
|
428
|
+
Rtype Legacy version: 0.0.1
|
429
|
+
Contracts version: 0.14.0
|
430
|
+
Rtype Legacy with native extension
|
431
|
+
Warming up --------------------------------------
|
432
|
+
pure 49.620k i/100ms
|
433
|
+
rtype-legacy 13.038k i/100ms
|
434
|
+
contracts 2.765k i/100ms
|
435
|
+
Calculating -------------------------------------
|
436
|
+
pure 2.037M (± 1.9%) i/s - 10.222M
|
437
|
+
rtype-legacy 179.155k (± 2.3%) i/s - 899.622k
|
438
|
+
contracts 30.576k (± 0.9%) i/s - 154.840k
|
439
|
+
|
440
|
+
Comparison:
|
441
|
+
pure: 2036909.8 i/s
|
442
|
+
rtype-legacy: 179155.3 i/s - 11.37x slower
|
443
|
+
contracts: 30575.8 i/s - 66.62x slower
|
444
|
+
```
|
445
|
+
|
446
|
+
### JRuby
|
447
|
+
```
|
448
|
+
Ruby version: 1.9.3
|
449
|
+
Ruby engine: jruby
|
450
|
+
Ruby description: jruby 1.7.23 (1.9.3p551) 2015-11-24 f496dd5 on Java HotSpot(TM) Server VM 1.8.0_91-b14 +jit [linux-i386]
|
451
|
+
Rtype Legacy version: 0.0.1
|
452
|
+
Contracts version: 0.14.0
|
453
|
+
Rtype Legacy with java extension
|
454
|
+
Warming up --------------------------------------
|
455
|
+
pure 76.140k i/100ms
|
456
|
+
rtype-legacy 5.123k i/100ms
|
457
|
+
contracts 1.422k i/100ms
|
458
|
+
Calculating -------------------------------------
|
459
|
+
pure 6.330M (± 9.7%) i/s - 30.913M
|
460
|
+
rtype-legacy 293.793k (± 4.4%) i/s - 1.465M
|
461
|
+
contracts 33.924k (± 2.3%) i/s - 170.640k
|
462
|
+
|
463
|
+
Comparison:
|
464
|
+
pure: 6329735.2 i/s
|
465
|
+
rtype-legacy: 293793.2 i/s - 21.54x slower
|
466
|
+
contracts: 33924.0 i/s - 186.59x slower
|
467
|
+
```
|
468
|
+
|
469
|
+
## Author
|
470
|
+
Sputnik Gugja (sputnikgugja@gmail.com)
|
471
|
+
|
472
|
+
## License
|
473
|
+
MIT license (@ Sputnik Gugja)
|
474
|
+
|
475
|
+
See `LICENSE` file.
|
data/Rakefile
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
require "rspec/core/rake_task"
|
2
|
+
|
3
|
+
# Default pattern is 'spec/**{,/*/**}/*_spec.rb'
|
4
|
+
RSpec::Core::RakeTask.new(:spec)
|
5
|
+
|
6
|
+
task :default => [:spec]
|
7
|
+
|
8
|
+
# Benchmark
|
9
|
+
desc "Compare with pure ruby and other gems"
|
10
|
+
task :benchmark do
|
11
|
+
ruby "benchmark/benchmark.rb"
|
12
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
require 'benchmark/ips'
|
2
|
+
|
3
|
+
require "rtype/legacy"
|
4
|
+
require "contracts"
|
5
|
+
require "contracts/version"
|
6
|
+
|
7
|
+
puts "Ruby version: #{RUBY_VERSION}"
|
8
|
+
puts "Ruby engine: #{RUBY_ENGINE}"
|
9
|
+
puts "Ruby description: #{RUBY_DESCRIPTION}"
|
10
|
+
|
11
|
+
puts "Rtype Legacy version: #{Rtype::Legacy::VERSION}"
|
12
|
+
puts "Contracts version: #{Contracts::VERSION}"
|
13
|
+
|
14
|
+
if !Rtype::Legacy::NATIVE_EXT_VERSION.nil?
|
15
|
+
puts "Rtype Legacy with native extension"
|
16
|
+
elsif !Rtype::Legacy::JAVA_EXT_VERSION.nil?
|
17
|
+
puts "Rtype Legacy with java extension"
|
18
|
+
else
|
19
|
+
puts "Rtype Legacy without native extension"
|
20
|
+
end
|
21
|
+
|
22
|
+
class PureTest
|
23
|
+
def sum(x, y)
|
24
|
+
x + y
|
25
|
+
end
|
26
|
+
|
27
|
+
def mul(x, y)
|
28
|
+
x * y
|
29
|
+
end
|
30
|
+
|
31
|
+
def args(a, b, c, d)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
pure_obj = PureTest.new
|
35
|
+
|
36
|
+
class RtypeTest
|
37
|
+
rtype [Numeric, Numeric] => Numeric
|
38
|
+
def sum(x, y)
|
39
|
+
x + y
|
40
|
+
end
|
41
|
+
|
42
|
+
rtype [:to_i, :to_i] => Numeric
|
43
|
+
def mul(x, y)
|
44
|
+
x * y
|
45
|
+
end
|
46
|
+
|
47
|
+
rtype [Integer, Numeric, String, :to_i] => Any
|
48
|
+
def args(a, b, c, d)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
rtype_obj = RtypeTest.new
|
52
|
+
|
53
|
+
class ContractsTest
|
54
|
+
include Contracts
|
55
|
+
|
56
|
+
Contract Num, Num => Num
|
57
|
+
def sum(x, y)
|
58
|
+
x + y
|
59
|
+
end
|
60
|
+
|
61
|
+
Contract RespondTo[:to_i], RespondTo[:to_i] => Num
|
62
|
+
def mul(x, y)
|
63
|
+
x * y
|
64
|
+
end
|
65
|
+
|
66
|
+
Contract Int, Num, String, RespondTo[:to_i] => Any
|
67
|
+
def args(a, b, c, d)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
contracts_obj = ContractsTest.new
|
71
|
+
|
72
|
+
Benchmark.ips do |x|
|
73
|
+
x.report("pure") do |times|
|
74
|
+
i = 0
|
75
|
+
while i < times
|
76
|
+
pure_obj.sum(1, 2)
|
77
|
+
pure_obj.mul(1, 2)
|
78
|
+
pure_obj.args(1, 2, "c", 4)
|
79
|
+
i += 1
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
x.report("rtype-legacy") do |times|
|
84
|
+
i = 0
|
85
|
+
while i < times
|
86
|
+
rtype_obj.sum(1, 2)
|
87
|
+
rtype_obj.mul(1, 2)
|
88
|
+
rtype_obj.args(1, 2, "c", 4)
|
89
|
+
i += 1
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
x.report("contracts") do |times|
|
94
|
+
i = 0
|
95
|
+
while i < times
|
96
|
+
contracts_obj.sum(1, 2)
|
97
|
+
contracts_obj.mul(1, 2)
|
98
|
+
contracts_obj.args(1, 2, "c", 4)
|
99
|
+
i += 1
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
x.compare!
|
104
|
+
end
|
Binary file
|