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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3bb8430c79ca97835ebdf6604e0c5afc4301f912db778e5f930fb9e699ae08c1
4
- data.tar.gz: 0557c3df900513e5ec7d45fec79fdf7502f0cb06a8e1538ff935e0228ef11136
3
+ metadata.gz: a234e4c63dea23906a65da0718515bff19ac7934a3e919535596042cfd605bba
4
+ data.tar.gz: 5bcb0f1f669a0e87de070c5095cf8f769ddf97dde4b2169060fb21769ffbd623
5
5
  SHA512:
6
- metadata.gz: 0ad03f0d27484914f45607d9e1fd7cfdaf8000d700e31f069b274b5f977f42a8736a3d03d0cba1f3d06679f0f5a05b56d7c3b4acfd2a90cce20e524de6f9154a
7
- data.tar.gz: 6f8e54590261939a43a52895921d80fb693a0e16361d011f53a80f1d7269aaade1e8871ae44374586ec488c026a02fced9057fdfcb300c532bd3a018498e954a
6
+ metadata.gz: 232d87a65618b51c3ec8756ad9d08bce53a49d50368d4629c8e694050502dddf12cdecd878193e40e09c8fcc13139b1a35383eedaa36a1660f7cf71f7e4d9810
7
+ data.tar.gz: 4cef62a76d8981fa7409e0d598448b35b4bb01794084ad2ab264741cbf0a78e6b9142352369892e124f130750847078f90297e5d1eda955881ebea0f13e96ec7
@@ -3,7 +3,10 @@ language: ruby
3
3
 
4
4
  sudo: false
5
5
 
6
- cache: bundler
6
+ cache:
7
+ bundler: true
8
+ directories:
9
+ - /home/travis/.rvm/
7
10
 
8
11
  rvm:
9
12
  - 2.2.0
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.
@@ -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
- __checkers__[kind] ||= begin
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 Checkable
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 Checkable
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 Checkable
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 Checkable
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 Checkable
253
+ extend Checker::Protocol
272
254
 
273
255
  def self.__kind; Object; end
274
256
 
@@ -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 Checkable
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
@@ -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
@@ -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 Checkable }
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)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Kind
4
- VERSION = '2.2.0'
4
+ VERSION = '2.3.0'
5
5
  end
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.2.0
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-23 00:00:00.000000000 Z
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