kind 2.0.0 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +178 -55
- data/lib/kind.rb +28 -2
- data/lib/kind/checker.rb +24 -16
- data/lib/kind/maybe.rb +28 -3
- data/lib/kind/types.rb +12 -1
- data/lib/kind/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a83d36b4c1fe131567251f418b775a8366ecf2a7c0d31682f801866cb9d83a27
|
4
|
+
data.tar.gz: b9b613500675aa1ea9e10c4b5ff83a451f289aec39896aaed025c196f0212ece
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 252e2e4f3bd9bbd09ff182579d450de170688ada607dfaa30cd70748c1ac4473381c856ba1be37f74ccd1eb05d077763cbf853ea1f356c58226408108e69f4e8
|
7
|
+
data.tar.gz: f35a606761e6de74f81427a4431c711252303f78e4b0b5d11dd5e1878180112c1733fa4fef85949f3414196e387b54c672e768384f92aff9ac1c434662529834
|
data/README.md
CHANGED
@@ -18,11 +18,14 @@ One of the goals of this project is to do simple type checking like `"some strin
|
|
18
18
|
- [Required Ruby version](#required-ruby-version)
|
19
19
|
- [Installation](#installation)
|
20
20
|
- [Usage](#usage)
|
21
|
-
- [Verifying the kind of some object](#verifying-the-kind-of-some-object)
|
22
|
-
|
21
|
+
- [Kind.of.\<Type\>() - Verifying the kind of some object](#kindoftype---verifying-the-kind-of-some-object)
|
22
|
+
- [Method aliases to perform a strict validation](#method-aliases-to-perform-a-strict-validation)
|
23
|
+
- [Kind.of.\<Type\>.or_nil()](#kindoftypeor_nil)
|
24
|
+
- [Kind.of.\<Type\>.instance?()](#kindoftypeinstance)
|
25
|
+
- [Kind.is.\<Type\>() - Verifying if some class/module is the expected kind.](#kindistype---verifying-if-some-classmodule-is-the-expected-kind)
|
23
26
|
- [How to create a new type checker?](#how-to-create-a-new-type-checker)
|
24
27
|
- [Creating/Verifiyng type checkers dynamically](#creatingverifiyng-type-checkers-dynamically)
|
25
|
-
- [Registering new (custom) type
|
28
|
+
- [Registering new (custom) type checker](#registering-new-custom-type-checker)
|
26
29
|
- [What happens if a custom type checker has a namespace?](#what-happens-if-a-custom-type-checker-has-a-namespace)
|
27
30
|
- [Type checkers](#type-checkers)
|
28
31
|
- [Classes' type checkers](#classes-type-checkers)
|
@@ -31,11 +34,15 @@ One of the goals of this project is to do simple type checking like `"some strin
|
|
31
34
|
- [Kind::Undefined](#kindundefined)
|
32
35
|
- [Kind.of.\<Type\>.or_undefined()](#kindoftypeor_undefined)
|
33
36
|
- [Kind::Maybe](#kindmaybe)
|
34
|
-
|
35
|
-
- [Kind::Maybe#
|
37
|
+
- [Replacing blocks by lambdas](#replacing-blocks-by-lambdas)
|
38
|
+
- [Kind::Maybe[] and Kind::Maybe#then method aliases](#kindmaybe-and-kindmaybethen-method-aliases)
|
39
|
+
- [Replacing blocks by lambdas](#replacing-blocks-by-lambdas-1)
|
40
|
+
- [Kind::None() and Kind::Some()](#kindnone-and-kindsome)
|
36
41
|
- [Kind.of.Maybe()](#kindofmaybe)
|
37
42
|
- [Kind::Optional](#kindoptional)
|
43
|
+
- [Replacing blocks by lambdas](#replacing-blocks-by-lambdas-2)
|
38
44
|
- [Kind.of.\<Type\>.as_optional](#kindoftypeas_optional)
|
45
|
+
- [Kind::Maybe#try](#kindmaybetry)
|
39
46
|
- [Kind::Validator (ActiveModel::Validations)](#kindvalidator-activemodelvalidations)
|
40
47
|
- [Usage](#usage-1)
|
41
48
|
- [Defining the default validation strategy](#defining-the-default-validation-strategy)
|
@@ -82,14 +89,14 @@ sum(1, 1) # 2
|
|
82
89
|
sum('1', 1) # Kind::Error ("\"1\" expected to be a kind of Numeric")
|
83
90
|
```
|
84
91
|
|
85
|
-
### Verifying the kind of some object
|
92
|
+
### Kind.of.\<Type\>() - Verifying the kind of some object
|
86
93
|
|
87
94
|
By default, basic verifications are strict. So, when you perform `Kind.of.Hash(value)`, if the given value was a Hash, the value itself will be returned, but if it isn't the right type, an error will be raised.
|
88
95
|
|
89
96
|
```ruby
|
90
|
-
Kind.of.Hash(nil)
|
91
|
-
Kind.of.Hash('')
|
92
|
-
Kind.of.Hash(
|
97
|
+
Kind.of.Hash(nil) # **raise Kind::Error, "nil expected to be a kind of Hash"**
|
98
|
+
Kind.of.Hash('') # raise Kind::Error, "'' expected to be a kind of Hash"
|
99
|
+
Kind.of.Hash(a: 1) # {a: 1}
|
93
100
|
|
94
101
|
# ---
|
95
102
|
|
@@ -99,14 +106,12 @@ Kind.of.Boolean(false) # false
|
|
99
106
|
```
|
100
107
|
|
101
108
|
> **Note:** `Kind.of.<Type>` supports the to_proc protocol.
|
102
|
-
>
|
103
|
-
> when the value has the desired kind and false if it hasn't.
|
109
|
+
> And it will perform a strict validation as expected.
|
104
110
|
|
105
111
|
```ruby
|
106
112
|
collection = [ {number: 1}, 'number 2', {number: 3}, :number_4 ]
|
107
113
|
|
108
|
-
collection
|
109
|
-
.select(&Kind.of.Hash) # [{number: 1}, {number: 3}]
|
114
|
+
collection.map(&Kind.of.Hash) # Kind::Error ("number 2" expected to be a kind of Hash)
|
110
115
|
```
|
111
116
|
|
112
117
|
When the verified value is nil, it is possible to define a default value with the same type to be returned.
|
@@ -123,6 +128,24 @@ Kind.of.Boolean(nil, or: true) # true
|
|
123
128
|
|
124
129
|
> **Note:** As an alternative syntax, you can use the `Kind::Of` instead of the `Kind.of` method. e.g: `Kind::Of::Hash('')`
|
125
130
|
|
131
|
+
#### Method aliases to perform a strict validation
|
132
|
+
|
133
|
+
```ruby
|
134
|
+
Kind.of.Hash[nil] # raise Kind::Error, "nil expected to be a kind of Hash"
|
135
|
+
Kind.of.Hash[''] # raise Kind::Error, "'' expected to be a kind of Hash"
|
136
|
+
Kind.of.Hash[a: 1] # {a: 1}
|
137
|
+
Kind.of.Hash['', or: {}] # {}
|
138
|
+
|
139
|
+
# or
|
140
|
+
|
141
|
+
Kind.of.Hash.instance(nil) # raise Kind::Error, "nil expected to be a kind of Hash"
|
142
|
+
Kind.of.Hash.instance('') # raise Kind::Error, "'' expected to be a kind of Hash"
|
143
|
+
Kind.of.Hash.instance(a: 1) # {a: 1}
|
144
|
+
Kind.of.Hash.instance('', or: {}) # {}
|
145
|
+
```
|
146
|
+
|
147
|
+
### Kind.of.\<Type\>.or_nil()
|
148
|
+
|
126
149
|
But if you don't need a strict type verification, use the `.or_nil` method.
|
127
150
|
|
128
151
|
```ruby
|
@@ -135,11 +158,12 @@ Kind.of.Boolean.or_nil('') # nil
|
|
135
158
|
Kind.of.Boolean.or_nil(true) # true
|
136
159
|
```
|
137
160
|
|
138
|
-
|
161
|
+
### Kind.of.\<Type\>.instance?()
|
162
|
+
|
163
|
+
Use the method `.instance?` to verify if the given object has the expected type.
|
139
164
|
|
140
165
|
```ruby
|
141
|
-
Kind.of.Hash.instance?('')
|
142
|
-
# false
|
166
|
+
Kind.of.Hash.instance?('') # false
|
143
167
|
|
144
168
|
# ---
|
145
169
|
|
@@ -155,27 +179,19 @@ Kind.of.Boolean.instance?(false) # true
|
|
155
179
|
collection = [ {number: 1}, 'number 2', {number: 3}, :number_4 ]
|
156
180
|
|
157
181
|
collection
|
158
|
-
.select(&Kind.of.Hash.instance?)
|
159
|
-
.reduce(0) { |total, item| total + item.fetch(:number, 0) } # 4
|
182
|
+
.select(&Kind.of.Hash.instance?) # [{:number=>1}, {:number=>3}]
|
160
183
|
```
|
161
184
|
|
162
|
-
|
185
|
+
> **Note:** You can use a different syntax to perform an instance verification.
|
186
|
+
> To do this, use Kind.of.\<Type\>?()
|
163
187
|
|
164
188
|
```ruby
|
165
|
-
|
166
|
-
Kind.of.Hash[''] # raise Kind::Error, "'' expected to be a kind of Hash"
|
167
|
-
Kind.of.Hash[a: 1] # {a: 1}
|
168
|
-
Kind.of.Hash['', or: {}] # {}
|
169
|
-
|
170
|
-
# or
|
189
|
+
collection = [ {number: 1}, 'number 2', {number: 3}, :number_4 ]
|
171
190
|
|
172
|
-
Kind.of.Hash
|
173
|
-
Kind.of.Hash.instance('') # raise Kind::Error, "'' expected to be a kind of Hash"
|
174
|
-
Kind.of.Hash.instance(a: 1) # {a: 1}
|
175
|
-
Kind.of.Hash.instance('', or: {}) # {}
|
191
|
+
collection.select(&Kind.of.Hash?) # [{:number=>1}, {:number=>3}]
|
176
192
|
```
|
177
193
|
|
178
|
-
###
|
194
|
+
### Kind.is.\<Type\>() - Verifying if some class/module is the expected kind.
|
179
195
|
|
180
196
|
You can use `Kind.is` to verify if some class has the expected type as its ancestor.
|
181
197
|
|
@@ -262,6 +278,22 @@ Kind.of(User, {}) # Kind::Error ({} expected to be a kind of User)
|
|
262
278
|
Kind.of(Hash, {}) # {}
|
263
279
|
Kind.of(Hash, user) # Kind::Error (<User ...> expected to be a kind of Hash)
|
264
280
|
|
281
|
+
# ----------------------------------------- #
|
282
|
+
# Verifiyng if the value is a kind instance #
|
283
|
+
# ----------------------------------------- #
|
284
|
+
|
285
|
+
Kind.of?(Numeric, 1) # true
|
286
|
+
Kind.of?(Numeric, 1, 2.0) # true
|
287
|
+
|
288
|
+
Kind.of?(Numeric, '1') # false
|
289
|
+
Kind.of?(Numeric, 1, '2.0') # false
|
290
|
+
|
291
|
+
# Note: Kind.of?(Type) without arguments will return a
|
292
|
+
# lambda that will perform an instance verification
|
293
|
+
#
|
294
|
+
[1, '2', 3.0, '4']
|
295
|
+
.select(&Kind.of?(Numeric)) # [1, 3.0]
|
296
|
+
|
265
297
|
# ---------------------------------- #
|
266
298
|
# Creating type checkers dynamically #
|
267
299
|
# ---------------------------------- #
|
@@ -300,7 +332,7 @@ end
|
|
300
332
|
Kind.is(User, AdminUser) # true
|
301
333
|
```
|
302
334
|
|
303
|
-
#### Registering new (custom) type
|
335
|
+
#### Registering new (custom) type checker
|
304
336
|
|
305
337
|
Use `Kind::Types.add()`. e.g:
|
306
338
|
|
@@ -491,7 +523,27 @@ puts optional.value_or(1) # 1
|
|
491
523
|
puts optional.value_or { 1 } # 1
|
492
524
|
```
|
493
525
|
|
494
|
-
|
526
|
+
#### Replacing blocks by lambdas
|
527
|
+
|
528
|
+
```ruby
|
529
|
+
Add = -> params do
|
530
|
+
a, b = Kind.of.Hash(params, or: Empty::HASH).values_at(:a, :b)
|
531
|
+
|
532
|
+
a + b if Kind.of.Numeric?(a, b)
|
533
|
+
end
|
534
|
+
|
535
|
+
# --
|
536
|
+
|
537
|
+
Kind::Maybe.new(a: 1, b: 2).map(&Add).value_or(0) # 3
|
538
|
+
|
539
|
+
# --
|
540
|
+
|
541
|
+
Kind::Maybe.new([]).map(&Add).value_or(0) # 0
|
542
|
+
Kind::Maybe.new({}).map(&Add).value_or(0) # 0
|
543
|
+
Kind::Maybe.new(nil).map(&Add).value_or(0) # 0
|
544
|
+
```
|
545
|
+
|
546
|
+
### Kind::Maybe[] and Kind::Maybe#then method aliases
|
495
547
|
|
496
548
|
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.
|
497
549
|
|
@@ -505,43 +557,57 @@ result =
|
|
505
557
|
puts result # 42
|
506
558
|
```
|
507
559
|
|
508
|
-
|
509
|
-
|
510
|
-
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.
|
560
|
+
#### Replacing blocks by lambdas
|
511
561
|
|
512
562
|
```ruby
|
513
|
-
|
563
|
+
Add = -> params do
|
564
|
+
a, b = Kind.of.Hash(params, or: Empty::HASH).values_at(:a, :b)
|
514
565
|
|
515
|
-
|
566
|
+
a + b if Kind.of.Numeric.instance?(a, b)
|
567
|
+
end
|
516
568
|
|
517
|
-
|
569
|
+
# --
|
518
570
|
|
519
|
-
|
571
|
+
Kind::Maybe[a: 1, b: 2].then(&Add).value_or(0) # 3
|
520
572
|
|
521
|
-
|
573
|
+
# --
|
522
574
|
|
523
|
-
|
524
|
-
#
|
525
|
-
|
575
|
+
Kind::Maybe[1].then(&Add).value_or(0) # 0
|
576
|
+
Kind::Maybe['2'].then(&Add).value_or(0) # 0
|
577
|
+
Kind::Maybe[nil].then(&Add).value_or(0) # 0
|
578
|
+
```
|
526
579
|
|
527
|
-
|
580
|
+
### Kind::None() and Kind::Some()
|
528
581
|
|
529
|
-
|
582
|
+
If you need to ensure the return of `Kind::Maybe` results from your methods/lambdas,
|
583
|
+
you could use the methods `Kind::None` and `Kind::Some` to do this. e.g:
|
530
584
|
|
531
|
-
|
585
|
+
```ruby
|
586
|
+
Add = -> params do
|
587
|
+
a, b = Kind.of.Hash(params, or: Empty::HASH).values_at(:a, :b)
|
532
588
|
|
533
|
-
|
534
|
-
# Kind::Undefined value #
|
535
|
-
#########################
|
589
|
+
return Kind::None unless Kind.of.Numeric.instance?(a, b)
|
536
590
|
|
537
|
-
|
591
|
+
Kind::Some(a + b)
|
592
|
+
end
|
538
593
|
|
539
|
-
|
594
|
+
# --
|
540
595
|
|
541
|
-
|
542
|
-
|
596
|
+
Add.call(1) # #<Kind::Maybe::None:0x0000... @value=nil>
|
597
|
+
Add.call({}) # #<Kind::Maybe::None:0x0000... @value=nil>
|
598
|
+
Add.call(a: 1) # #<Kind::Maybe::None:0x0000... @value=nil>
|
599
|
+
Add.call(b: 2) # #<Kind::Maybe::None:0x0000... @value=nil>
|
543
600
|
|
544
|
-
|
601
|
+
Add.call(a:1, b: 2) # #<Kind::Maybe::Some:0x0000... @value=3>
|
602
|
+
|
603
|
+
# --
|
604
|
+
|
605
|
+
Kind::Maybe[a: 1, b: 2].then(&Add).value_or(0) # 3
|
606
|
+
|
607
|
+
Kind::Maybe[1].then(&Add).value_or(0) # 0
|
608
|
+
Kind::Maybe['2'].then(&Add).value_or(0) # 0
|
609
|
+
Kind::Maybe[nil].then(&Add).value_or(0) # 0
|
610
|
+
```
|
545
611
|
|
546
612
|
### Kind.of.Maybe()
|
547
613
|
|
@@ -598,6 +664,26 @@ result2 =
|
|
598
664
|
puts result2 # 35
|
599
665
|
```
|
600
666
|
|
667
|
+
#### Replacing blocks by lambdas
|
668
|
+
|
669
|
+
```ruby
|
670
|
+
Add = -> params do
|
671
|
+
a, b = Kind.of.Hash(params, or: Empty::HASH).values_at(:a, :b)
|
672
|
+
|
673
|
+
a + b if Kind.of.Numeric.instance?(a, b)
|
674
|
+
end
|
675
|
+
|
676
|
+
# --
|
677
|
+
|
678
|
+
Kind::Optional[a: 1, b: 2].then(&Add).value_or(0) # 3
|
679
|
+
|
680
|
+
# --
|
681
|
+
|
682
|
+
Kind::Optional[1].then(&Add).value_or(0) # 0
|
683
|
+
Kind::Optional['2'].then(&Add).value_or(0) # 0
|
684
|
+
Kind::Optional[nil].then(&Add).value_or(0) # 0
|
685
|
+
```
|
686
|
+
|
601
687
|
**Note:** The `Kind.of.Optional` is available to check if some value is a `Kind::Optional`.
|
602
688
|
|
603
689
|
[⬆️ Back to Top](#table-of-contents-)
|
@@ -709,6 +795,44 @@ end
|
|
709
795
|
|
710
796
|
[⬆️ Back to Top](#table-of-contents-)
|
711
797
|
|
798
|
+
### Kind::Maybe#try
|
799
|
+
|
800
|
+
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.
|
801
|
+
|
802
|
+
```ruby
|
803
|
+
object = 'foo'
|
804
|
+
|
805
|
+
p Kind::Maybe[object].try(:upcase) # "FOO"
|
806
|
+
|
807
|
+
p Kind::Maybe[{}].try(:fetch, :number, 0) # 0
|
808
|
+
|
809
|
+
p Kind::Maybe[{number: 1}].try(:fetch, :number) # 1
|
810
|
+
|
811
|
+
p Kind::Maybe[object].try { |value| value.upcase } # "FOO"
|
812
|
+
|
813
|
+
#############
|
814
|
+
# Nil value #
|
815
|
+
#############
|
816
|
+
|
817
|
+
object = nil
|
818
|
+
|
819
|
+
p Kind::Maybe[object].try(:upcase) # nil
|
820
|
+
|
821
|
+
p Kind::Maybe[object].try { |value| value.upcase } # nil
|
822
|
+
|
823
|
+
#########################
|
824
|
+
# Kind::Undefined value #
|
825
|
+
#########################
|
826
|
+
|
827
|
+
object = Kind::Undefined
|
828
|
+
|
829
|
+
p Kind::Maybe[object].try(:upcase) # nil
|
830
|
+
|
831
|
+
p Kind::Maybe[object].try { |value| value.upcase } # nil
|
832
|
+
```
|
833
|
+
|
834
|
+
[⬆️ Back to Top](#table-of-contents-)
|
835
|
+
|
712
836
|
## Kind::Validator (ActiveModel::Validations)
|
713
837
|
|
714
838
|
This module enables the capability to validate types via [`ActiveModel::Validations >= 3.2, < 6.1.0`](https://api.rubyonrails.org/classes/ActiveModel/Validations.html). e.g
|
@@ -839,7 +963,6 @@ Kind::Validator.default_strategy = :instance_of
|
|
839
963
|
```
|
840
964
|
|
841
965
|
And these are the available options to define the default strategy:
|
842
|
-
- `is_a`
|
843
966
|
- `kind_of` *(default)*
|
844
967
|
- `instance_of`
|
845
968
|
|
data/lib/kind.rb
CHANGED
@@ -29,6 +29,12 @@ module Kind
|
|
29
29
|
|
30
30
|
private_constant :MODULE_OR_CLASS
|
31
31
|
|
32
|
+
private_class_method def self.__checkers__
|
33
|
+
@__checkers__ ||= {}
|
34
|
+
end
|
35
|
+
|
36
|
+
__checkers__
|
37
|
+
|
32
38
|
def self.of(kind = Undefined, object = Undefined)
|
33
39
|
return Of if kind == Undefined && object == Undefined
|
34
40
|
|
@@ -45,8 +51,8 @@ module Kind
|
|
45
51
|
end
|
46
52
|
end
|
47
53
|
|
48
|
-
|
49
|
-
|
54
|
+
def self.of?(kind, *args)
|
55
|
+
Kind.of(kind).instance?(*args)
|
50
56
|
end
|
51
57
|
|
52
58
|
# --------------------- #
|
@@ -90,6 +96,10 @@ module Kind
|
|
90
96
|
def self.__is_instance__(value); class?(value); end
|
91
97
|
end)
|
92
98
|
|
99
|
+
def self.Class?(*args)
|
100
|
+
Kind::Of::Class.instance?(*args)
|
101
|
+
end
|
102
|
+
|
93
103
|
# -- Module
|
94
104
|
|
95
105
|
def self.Module(object = Undefined)
|
@@ -136,6 +146,10 @@ module Kind
|
|
136
146
|
def self.__is_instance__(value); class?(value); end
|
137
147
|
end)
|
138
148
|
|
149
|
+
def self.Module?(*args)
|
150
|
+
Kind::Of::Module.instance?(*args)
|
151
|
+
end
|
152
|
+
|
139
153
|
# -- Boolean
|
140
154
|
|
141
155
|
def self.Boolean(object = Undefined, options = Empty::HASH)
|
@@ -187,6 +201,10 @@ module Kind
|
|
187
201
|
end
|
188
202
|
end)
|
189
203
|
|
204
|
+
def self.Boolean?(*args)
|
205
|
+
Kind::Of::Boolean.instance?(*args)
|
206
|
+
end
|
207
|
+
|
190
208
|
# -- Lambda
|
191
209
|
|
192
210
|
def self.Lambda(object = Undefined, options = Empty::HASH)
|
@@ -231,6 +249,10 @@ module Kind
|
|
231
249
|
end
|
232
250
|
end)
|
233
251
|
|
252
|
+
def self.Lambda?(*args)
|
253
|
+
Kind::Of::Lambda.instance?(*args)
|
254
|
+
end
|
255
|
+
|
234
256
|
# -- Callable
|
235
257
|
|
236
258
|
def self.Callable(object = Undefined, options = Empty::HASH)
|
@@ -279,6 +301,10 @@ module Kind
|
|
279
301
|
end
|
280
302
|
end)
|
281
303
|
|
304
|
+
def self.Callable?(*args)
|
305
|
+
Kind::Of::Callable.instance?(*args)
|
306
|
+
end
|
307
|
+
|
282
308
|
# ---------------------- #
|
283
309
|
# Built-in type checkers #
|
284
310
|
# ---------------------- #
|
data/lib/kind/checker.rb
CHANGED
@@ -18,21 +18,29 @@ module Kind
|
|
18
18
|
instance(value, options)
|
19
19
|
end
|
20
20
|
|
21
|
-
def
|
22
|
-
|
23
|
-
|
24
|
-
to_proc
|
21
|
+
def to_proc
|
22
|
+
@to_proc ||=
|
23
|
+
-> checker { -> value { checker.instance(value) } }.call(self)
|
25
24
|
end
|
26
25
|
|
27
26
|
def __is_instance__(value)
|
28
|
-
value.
|
27
|
+
value.kind_of?(__kind)
|
29
28
|
end
|
30
29
|
|
31
|
-
def
|
32
|
-
@
|
30
|
+
def is_instance_to_proc
|
31
|
+
@is_instance_to_proc ||=
|
33
32
|
-> checker { -> value { checker.__is_instance__(value) } }.call(self)
|
34
33
|
end
|
35
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
|
+
arg == Kind::Undefined ? is_instance_to_proc : __is_instance__(arg)
|
42
|
+
end
|
43
|
+
|
36
44
|
def or_nil(value)
|
37
45
|
return value if instance?(value)
|
38
46
|
end
|
@@ -41,6 +49,15 @@ module Kind
|
|
41
49
|
or_nil(value) || Kind::Undefined
|
42
50
|
end
|
43
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
|
+
|
44
61
|
def as_maybe(value = Kind::Undefined)
|
45
62
|
return __as_maybe__(value) if value != Kind::Undefined
|
46
63
|
|
@@ -50,15 +67,6 @@ module Kind
|
|
50
67
|
def as_optional(value = Kind::Undefined)
|
51
68
|
as_maybe(value)
|
52
69
|
end
|
53
|
-
|
54
|
-
def __as_maybe__(value)
|
55
|
-
Kind::Maybe.new(or_nil(value))
|
56
|
-
end
|
57
|
-
|
58
|
-
def as_maybe_to_proc
|
59
|
-
@as_maybe_to_proc ||=
|
60
|
-
-> checker { -> value { checker.__as_maybe__(value) } }.call(self)
|
61
|
-
end
|
62
70
|
end
|
63
71
|
|
64
72
|
private_constant :Checkable
|
data/lib/kind/maybe.rb
CHANGED
@@ -16,7 +16,7 @@ module Kind
|
|
16
16
|
attr_reader :value
|
17
17
|
|
18
18
|
def initialize(value)
|
19
|
-
@value = value
|
19
|
+
@value = value.kind_of?(Result) ? value.value : value
|
20
20
|
end
|
21
21
|
|
22
22
|
def value_or(method_name = Undefined, &block)
|
@@ -44,7 +44,7 @@ module Kind
|
|
44
44
|
def value_or(default = Undefined, &block)
|
45
45
|
raise ArgumentError, INVALID_DEFAULT_ARG if default == Undefined && !block
|
46
46
|
|
47
|
-
|
47
|
+
default != Undefined ? default : block.call
|
48
48
|
end
|
49
49
|
|
50
50
|
def none?; true; end
|
@@ -79,6 +79,7 @@ module Kind
|
|
79
79
|
def map(&fn)
|
80
80
|
result = fn.call(@value)
|
81
81
|
|
82
|
+
return result if Maybe::None === result
|
82
83
|
return NONE_WITH_NIL_VALUE if result == nil
|
83
84
|
return NONE_WITH_UNDEFINED_VALUE if result == Undefined
|
84
85
|
|
@@ -98,13 +99,37 @@ module Kind
|
|
98
99
|
|
99
100
|
def self.new(value)
|
100
101
|
result_type = Maybe::Value.none?(value) ? None : Some
|
101
|
-
result_type.new(value
|
102
|
+
result_type.new(value)
|
102
103
|
end
|
103
104
|
|
104
105
|
def self.[](value);
|
105
106
|
new(value)
|
106
107
|
end
|
108
|
+
|
109
|
+
def self.none
|
110
|
+
NONE_WITH_NIL_VALUE
|
111
|
+
end
|
112
|
+
|
113
|
+
VALUE_CANT_BE_NONE = "value can't be nil or Kind::Undefined".freeze
|
114
|
+
|
115
|
+
private_constant :VALUE_CANT_BE_NONE
|
116
|
+
|
117
|
+
def self.some(value)
|
118
|
+
return Maybe::Some.new(value) if Value.some?(value)
|
119
|
+
|
120
|
+
raise ArgumentError, VALUE_CANT_BE_NONE
|
121
|
+
end
|
107
122
|
end
|
108
123
|
|
109
124
|
Optional = Maybe
|
125
|
+
|
126
|
+
None = Maybe.none
|
127
|
+
|
128
|
+
def self.None
|
129
|
+
Kind::None
|
130
|
+
end
|
131
|
+
|
132
|
+
def self.Some(value)
|
133
|
+
Maybe.some(value)
|
134
|
+
end
|
110
135
|
end
|
data/lib/kind/types.rb
CHANGED
@@ -12,7 +12,17 @@ module Kind
|
|
12
12
|
|
13
13
|
return Kind::Of::%{kind_name} if object == Undefined && default.nil?
|
14
14
|
|
15
|
-
Kind::Of
|
15
|
+
is_instance = Kind::Of::%{kind_name}.__is_instance__(object)
|
16
|
+
|
17
|
+
return object if is_instance
|
18
|
+
|
19
|
+
Kind::Of.(::%{kind_name_to_check}, object && default ? default : object || default)
|
20
|
+
end
|
21
|
+
RUBY
|
22
|
+
|
23
|
+
KIND_OF_IS = <<-RUBY
|
24
|
+
def self.%{method_name}?(*args)
|
25
|
+
Kind::Of::%{kind_name}.instance?(*args)
|
16
26
|
end
|
17
27
|
RUBY
|
18
28
|
|
@@ -93,6 +103,7 @@ module Kind
|
|
93
103
|
|
94
104
|
kind_of_mod.instance_eval(KIND_OF % params)
|
95
105
|
kind_of_mod.const_set(method_name, kind_checker)
|
106
|
+
kind_of_mod.instance_eval(KIND_OF_IS % params)
|
96
107
|
end
|
97
108
|
|
98
109
|
unless kind_is_mod.respond_to?(method_name)
|
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.1.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-05-
|
11
|
+
date: 2020-05-12 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:
|