kind 2.2.0 → 2.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +4 -1
- data/README.md +56 -2
- data/lib/kind.rb +7 -25
- data/lib/kind/checker.rb +3 -71
- data/lib/kind/checker/factory.rb +35 -0
- data/lib/kind/checker/protocol.rb +73 -0
- data/lib/kind/maybe.rb +26 -1
- data/lib/kind/types.rb +1 -1
- data/lib/kind/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a234e4c63dea23906a65da0718515bff19ac7934a3e919535596042cfd605bba
|
4
|
+
data.tar.gz: 5bcb0f1f669a0e87de070c5095cf8f769ddf97dde4b2169060fb21769ffbd623
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 232d87a65618b51c3ec8756ad9d08bce53a49d50368d4629c8e694050502dddf12cdecd878193e40e09c8fcc13139b1a35383eedaa36a1660f7cf71f7e4d9810
|
7
|
+
data.tar.gz: 4cef62a76d8981fa7409e0d598448b35b4bb01794084ad2ab264741cbf0a78e6b9142352369892e124f130750847078f90297e5d1eda955881ebea0f13e96ec7
|
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -39,13 +39,14 @@ One of the goals of this project is to do simple type checking like `"some strin
|
|
39
39
|
- [Kind.of.\<Type\>.or_undefined()](#kindoftypeor_undefined)
|
40
40
|
- [Kind::Maybe](#kindmaybe)
|
41
41
|
- [Replacing blocks by lambdas](#replacing-blocks-by-lambdas)
|
42
|
-
- [Kind::Maybe[] and Kind::Maybe#then method aliases](#kindmaybe-and-kindmaybethen-method-aliases)
|
42
|
+
- [Kind::Maybe[], Kind::Maybe.wrap() and Kind::Maybe#then method aliases](#kindmaybe-kindmaybewrap-and-kindmaybethen-method-aliases)
|
43
43
|
- [Replacing blocks by lambdas](#replacing-blocks-by-lambdas-1)
|
44
44
|
- [Kind::None() and Kind::Some()](#kindnone-and-kindsome)
|
45
45
|
- [Kind.of.Maybe()](#kindofmaybe)
|
46
46
|
- [Kind::Optional](#kindoptional)
|
47
47
|
- [Replacing blocks by lambdas](#replacing-blocks-by-lambdas-2)
|
48
48
|
- [Kind.of.\<Type\>.as_optional](#kindoftypeas_optional)
|
49
|
+
- [Kind::Maybe(<Type>)](#kindmaybetype)
|
49
50
|
- [Kind::Maybe#try](#kindmaybetry)
|
50
51
|
- [Kind::Empty](#kindempty)
|
51
52
|
- [Similar Projects](#similar-projects)
|
@@ -717,7 +718,7 @@ end
|
|
717
718
|
Kind::Maybe.new(nil).map(&Add).value_or(0) # 0
|
718
719
|
```
|
719
720
|
|
720
|
-
### Kind::Maybe[] and Kind::Maybe#then method aliases
|
721
|
+
### Kind::Maybe[], Kind::Maybe.wrap() and Kind::Maybe#then method aliases
|
721
722
|
|
722
723
|
You can use `Kind::Maybe[]` (brackets) instead of the `.new` to transform values in a `Kind::Maybe`. Another alias is `.then` to the `.map` method.
|
723
724
|
|
@@ -731,6 +732,19 @@ result =
|
|
731
732
|
puts result # 42
|
732
733
|
```
|
733
734
|
|
735
|
+
You can also use `Kind::Maybe.wrap()` instead of the `.new` method.
|
736
|
+
|
737
|
+
```ruby
|
738
|
+
result =
|
739
|
+
Kind::Maybe
|
740
|
+
.wrap(5)
|
741
|
+
.then { |value| value * 5 }
|
742
|
+
.then { |value| value + 17 }
|
743
|
+
.value_or(0)
|
744
|
+
|
745
|
+
puts result # 42
|
746
|
+
```
|
747
|
+
|
734
748
|
#### Replacing blocks by lambdas
|
735
749
|
|
736
750
|
```ruby
|
@@ -969,6 +983,46 @@ end
|
|
969
983
|
|
970
984
|
[⬆️ Back to Top](#table-of-contents-)
|
971
985
|
|
986
|
+
### Kind::Maybe(<Type>)
|
987
|
+
|
988
|
+
There is an alternative to `Kind.of.\<Type\>.as_optional`, you can use `Kind::Optional(<Type>)` to create a maybe monad which will return None if the given input hasn't the expected type. e.g:
|
989
|
+
|
990
|
+
```ruby
|
991
|
+
result1 =
|
992
|
+
Kind::Maybe(Numeric)
|
993
|
+
.wrap(5)
|
994
|
+
.then { |value| value * 5 }
|
995
|
+
.value_or { 0 }
|
996
|
+
|
997
|
+
puts result1 # 25
|
998
|
+
|
999
|
+
# ---
|
1000
|
+
|
1001
|
+
result2 =
|
1002
|
+
Kind::Optional(Numeric)
|
1003
|
+
.wrap('5')
|
1004
|
+
.then { |value| value * 5 }
|
1005
|
+
.value_or { 0 }
|
1006
|
+
|
1007
|
+
puts result2 # 0
|
1008
|
+
```
|
1009
|
+
|
1010
|
+
This typed maybe has the same methods of `Kind::Maybe` class. e.g:
|
1011
|
+
|
1012
|
+
```ruby
|
1013
|
+
Kind::Maybe(Numeric)[5]
|
1014
|
+
Kind::Maybe(Numeric).new(5)
|
1015
|
+
Kind::Maybe(Numeric).wrap(5)
|
1016
|
+
|
1017
|
+
# ---
|
1018
|
+
|
1019
|
+
Kind::Optional(Numeric)[5]
|
1020
|
+
Kind::Optional(Numeric).new(5)
|
1021
|
+
Kind::Optional(Numeric).wrap(5)
|
1022
|
+
```
|
1023
|
+
|
1024
|
+
[⬆️ Back to Top](#table-of-contents-)
|
1025
|
+
|
972
1026
|
### Kind::Maybe#try
|
973
1027
|
|
974
1028
|
If you don't want to use a map to access the value, you could use the `#try` method to access it. So, if the value wasn't `nil` or `Kind::Undefined`, it will be returned.
|
data/lib/kind.rb
CHANGED
@@ -4,12 +4,12 @@ require 'kind/version'
|
|
4
4
|
|
5
5
|
require 'kind/empty'
|
6
6
|
require 'kind/undefined'
|
7
|
+
require 'kind/checker'
|
7
8
|
require 'kind/maybe'
|
8
9
|
|
9
10
|
require 'kind/error'
|
10
11
|
require 'kind/of'
|
11
12
|
require 'kind/is'
|
12
|
-
require 'kind/checker'
|
13
13
|
require 'kind/types'
|
14
14
|
|
15
15
|
module Kind
|
@@ -25,30 +25,12 @@ module Kind
|
|
25
25
|
raise ArgumentError, WRONG_NUMBER_OF_ARGUMENTS
|
26
26
|
end
|
27
27
|
|
28
|
-
MODULE_OR_CLASS = 'Module/Class'.freeze
|
29
|
-
|
30
|
-
private_constant :MODULE_OR_CLASS
|
31
|
-
|
32
|
-
private_class_method def self.__checkers__
|
33
|
-
@__checkers__ ||= {}
|
34
|
-
end
|
35
|
-
|
36
|
-
__checkers__
|
37
|
-
|
38
28
|
def self.of(kind = Undefined, object = Undefined)
|
39
29
|
return Of if Undefined == kind && Undefined == object
|
40
30
|
|
41
31
|
return Kind::Of.(kind, object) if Undefined != object
|
42
32
|
|
43
|
-
|
44
|
-
kind_name = kind.name
|
45
|
-
|
46
|
-
if Kind::Of.const_defined?(kind_name, false)
|
47
|
-
Kind::Of.const_get(kind_name)
|
48
|
-
else
|
49
|
-
Checker.new(Kind::Of.(Module, kind, MODULE_OR_CLASS))
|
50
|
-
end
|
51
|
-
end
|
33
|
+
Kind::Checker::Factory.create(kind)
|
52
34
|
end
|
53
35
|
|
54
36
|
def self.of?(kind, *args)
|
@@ -87,7 +69,7 @@ module Kind
|
|
87
69
|
end
|
88
70
|
|
89
71
|
const_set(:Class, ::Module.new do
|
90
|
-
extend
|
72
|
+
extend Checker::Protocol
|
91
73
|
|
92
74
|
def self.__kind; ::Class; end
|
93
75
|
|
@@ -109,7 +91,7 @@ module Kind
|
|
109
91
|
end
|
110
92
|
|
111
93
|
const_set(:Module, ::Module.new do
|
112
|
-
extend
|
94
|
+
extend Checker::Protocol
|
113
95
|
|
114
96
|
def self.__kind_undefined(value)
|
115
97
|
__kind_error(Kind::Undefined) if Kind::Undefined == value
|
@@ -165,7 +147,7 @@ module Kind
|
|
165
147
|
end
|
166
148
|
|
167
149
|
const_set(:Boolean, ::Module.new do
|
168
|
-
extend
|
150
|
+
extend Checker::Protocol
|
169
151
|
|
170
152
|
def self.__kind; [TrueClass, FalseClass].freeze; end
|
171
153
|
|
@@ -220,7 +202,7 @@ module Kind
|
|
220
202
|
end
|
221
203
|
|
222
204
|
const_set(:Lambda, ::Module.new do
|
223
|
-
extend
|
205
|
+
extend Checker::Protocol
|
224
206
|
|
225
207
|
def self.__kind; ::Proc; end
|
226
208
|
|
@@ -268,7 +250,7 @@ module Kind
|
|
268
250
|
end
|
269
251
|
|
270
252
|
const_set(:Callable, ::Module.new do
|
271
|
-
extend
|
253
|
+
extend Checker::Protocol
|
272
254
|
|
273
255
|
def self.__kind; Object; end
|
274
256
|
|
data/lib/kind/checker.rb
CHANGED
@@ -1,78 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'kind/checker/factory'
|
4
|
+
require 'kind/checker/protocol'
|
3
5
|
module Kind
|
4
|
-
module Checkable
|
5
|
-
def class?(value)
|
6
|
-
Kind::Is.__call__(__kind, value)
|
7
|
-
end
|
8
|
-
|
9
|
-
def instance(value, options = Empty::HASH)
|
10
|
-
default = options[:or]
|
11
|
-
|
12
|
-
return Kind::Of.(__kind, value) if ::Kind::Maybe::Value.none?(default)
|
13
|
-
|
14
|
-
Kind::Undefined != value && instance?(value) ? value : Kind::Of.(__kind, default)
|
15
|
-
end
|
16
|
-
|
17
|
-
def [](value, options = options = Empty::HASH)
|
18
|
-
instance(value, options)
|
19
|
-
end
|
20
|
-
|
21
|
-
def to_proc
|
22
|
-
@to_proc ||=
|
23
|
-
-> checker { -> value { checker.instance(value) } }.call(self)
|
24
|
-
end
|
25
|
-
|
26
|
-
def __is_instance__(value)
|
27
|
-
value.kind_of?(__kind)
|
28
|
-
end
|
29
|
-
|
30
|
-
def is_instance_to_proc
|
31
|
-
@is_instance_to_proc ||=
|
32
|
-
-> checker { -> value { checker.__is_instance__(value) } }.call(self)
|
33
|
-
end
|
34
|
-
|
35
|
-
def instance?(*args)
|
36
|
-
return is_instance_to_proc if args.empty?
|
37
|
-
|
38
|
-
return args.all? { |object| __is_instance__(object) } if args.size > 1
|
39
|
-
|
40
|
-
arg = args[0]
|
41
|
-
Kind::Undefined == arg ? is_instance_to_proc : __is_instance__(arg)
|
42
|
-
end
|
43
|
-
|
44
|
-
def or_nil(value)
|
45
|
-
return value if instance?(value)
|
46
|
-
end
|
47
|
-
|
48
|
-
def or_undefined(value)
|
49
|
-
or_nil(value) || Kind::Undefined
|
50
|
-
end
|
51
|
-
|
52
|
-
def __as_maybe__(value)
|
53
|
-
Kind::Maybe.new(or_nil(value))
|
54
|
-
end
|
55
|
-
|
56
|
-
def as_maybe_to_proc
|
57
|
-
@as_maybe_to_proc ||=
|
58
|
-
-> checker { -> value { checker.__as_maybe__(value) } }.call(self)
|
59
|
-
end
|
60
|
-
|
61
|
-
def as_maybe(value = Kind::Undefined)
|
62
|
-
return __as_maybe__(value) if Kind::Undefined != value
|
63
|
-
|
64
|
-
as_maybe_to_proc
|
65
|
-
end
|
66
|
-
|
67
|
-
def as_optional(value = Kind::Undefined)
|
68
|
-
as_maybe(value)
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
private_constant :Checkable
|
73
|
-
|
74
6
|
class Checker
|
75
|
-
include
|
7
|
+
include Protocol
|
76
8
|
|
77
9
|
attr_reader :__kind
|
78
10
|
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'singleton'
|
4
|
+
|
5
|
+
module Kind
|
6
|
+
class Checker
|
7
|
+
class Factory
|
8
|
+
include Singleton
|
9
|
+
|
10
|
+
def self.create(kind)
|
11
|
+
instance.create(kind)
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize
|
15
|
+
@__checkers__ = {}
|
16
|
+
end
|
17
|
+
|
18
|
+
MODULE_OR_CLASS = 'Module/Class'.freeze
|
19
|
+
|
20
|
+
private_constant :MODULE_OR_CLASS
|
21
|
+
|
22
|
+
def create(kind)
|
23
|
+
@__checkers__[kind] ||= begin
|
24
|
+
kind_name = kind.name
|
25
|
+
|
26
|
+
if Kind::Of.const_defined?(kind_name, false)
|
27
|
+
Kind::Of.const_get(kind_name)
|
28
|
+
else
|
29
|
+
Kind::Checker.new(Kind::Of.(Module, kind, MODULE_OR_CLASS))
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Kind
|
4
|
+
class Checker
|
5
|
+
module Protocol
|
6
|
+
def class?(value)
|
7
|
+
Kind::Is.__call__(__kind, value)
|
8
|
+
end
|
9
|
+
|
10
|
+
def instance(value, options = Empty::HASH)
|
11
|
+
default = options[:or]
|
12
|
+
|
13
|
+
return Kind::Of.(__kind, value) if ::Kind::Maybe::Value.none?(default)
|
14
|
+
|
15
|
+
Kind::Undefined != value && instance?(value) ? value : Kind::Of.(__kind, default)
|
16
|
+
end
|
17
|
+
|
18
|
+
def [](value, options = options = Empty::HASH)
|
19
|
+
instance(value, options)
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_proc
|
23
|
+
@to_proc ||=
|
24
|
+
-> checker { -> value { checker.instance(value) } }.call(self)
|
25
|
+
end
|
26
|
+
|
27
|
+
def __is_instance__(value)
|
28
|
+
value.kind_of?(__kind)
|
29
|
+
end
|
30
|
+
|
31
|
+
def is_instance_to_proc
|
32
|
+
@is_instance_to_proc ||=
|
33
|
+
-> checker { -> value { checker.__is_instance__(value) } }.call(self)
|
34
|
+
end
|
35
|
+
|
36
|
+
def instance?(*args)
|
37
|
+
return is_instance_to_proc if args.empty?
|
38
|
+
|
39
|
+
return args.all? { |object| __is_instance__(object) } if args.size > 1
|
40
|
+
|
41
|
+
arg = args[0]
|
42
|
+
Kind::Undefined == arg ? is_instance_to_proc : __is_instance__(arg)
|
43
|
+
end
|
44
|
+
|
45
|
+
def or_nil(value)
|
46
|
+
return value if instance?(value)
|
47
|
+
end
|
48
|
+
|
49
|
+
def or_undefined(value)
|
50
|
+
or_nil(value) || Kind::Undefined
|
51
|
+
end
|
52
|
+
|
53
|
+
def __as_maybe__(value)
|
54
|
+
Kind::Maybe.new(or_nil(value))
|
55
|
+
end
|
56
|
+
|
57
|
+
def as_maybe_to_proc
|
58
|
+
@as_maybe_to_proc ||=
|
59
|
+
-> checker { -> value { checker.__as_maybe__(value) } }.call(self)
|
60
|
+
end
|
61
|
+
|
62
|
+
def as_maybe(value = Kind::Undefined)
|
63
|
+
return __as_maybe__(value) if Kind::Undefined != value
|
64
|
+
|
65
|
+
as_maybe_to_proc
|
66
|
+
end
|
67
|
+
|
68
|
+
def as_optional(value = Kind::Undefined)
|
69
|
+
as_maybe(value)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
data/lib/kind/maybe.rb
CHANGED
@@ -2,6 +2,19 @@
|
|
2
2
|
|
3
3
|
module Kind
|
4
4
|
module Maybe
|
5
|
+
class Typed
|
6
|
+
def initialize(kind)
|
7
|
+
@kind_checker = Kind::Checker::Factory.create(kind)
|
8
|
+
end
|
9
|
+
|
10
|
+
def wrap(value)
|
11
|
+
@kind_checker.as_maybe(value)
|
12
|
+
end
|
13
|
+
|
14
|
+
alias_method :new, :wrap
|
15
|
+
alias_method :[], :wrap
|
16
|
+
end
|
17
|
+
|
5
18
|
module Value
|
6
19
|
def self.none?(value)
|
7
20
|
value.nil? || Undefined == value
|
@@ -102,7 +115,11 @@ module Kind
|
|
102
115
|
result_type.new(value)
|
103
116
|
end
|
104
117
|
|
105
|
-
def self.[](value)
|
118
|
+
def self.[](value)
|
119
|
+
new(value)
|
120
|
+
end
|
121
|
+
|
122
|
+
def self.wrap(value)
|
106
123
|
new(value)
|
107
124
|
end
|
108
125
|
|
@@ -132,4 +149,12 @@ module Kind
|
|
132
149
|
def self.Some(value)
|
133
150
|
Maybe.some(value)
|
134
151
|
end
|
152
|
+
|
153
|
+
def self.Maybe(kind)
|
154
|
+
Maybe::Typed.new(kind)
|
155
|
+
end
|
156
|
+
|
157
|
+
def self.Optional(kind)
|
158
|
+
Maybe::Typed.new(kind)
|
159
|
+
end
|
135
160
|
end
|
data/lib/kind/types.rb
CHANGED
@@ -98,7 +98,7 @@ module Kind
|
|
98
98
|
kind_name = params[:kind_name]
|
99
99
|
params[:kind_name_to_check] ||= kind_name
|
100
100
|
|
101
|
-
kind_checker = ::Module.new { extend
|
101
|
+
kind_checker = ::Module.new { extend Checker::Protocol }
|
102
102
|
kind_checker.module_eval("def self.__kind; #{params[:kind_name_to_check]}; end")
|
103
103
|
|
104
104
|
kind_of_mod.instance_eval(KIND_OF % params)
|
data/lib/kind/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kind
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Rodrigo Serradura
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-06-
|
11
|
+
date: 2020-06-25 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: A simple type system (at runtime) for Ruby - free of dependencies.
|
14
14
|
email:
|
@@ -32,6 +32,8 @@ files:
|
|
32
32
|
- lib/kind/active_model/kind_validator.rb
|
33
33
|
- lib/kind/active_model/validation.rb
|
34
34
|
- lib/kind/checker.rb
|
35
|
+
- lib/kind/checker/factory.rb
|
36
|
+
- lib/kind/checker/protocol.rb
|
35
37
|
- lib/kind/empty.rb
|
36
38
|
- lib/kind/error.rb
|
37
39
|
- lib/kind/is.rb
|