kind 5.0.0 → 5.4.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.
- checksums.yaml +4 -4
- data/.tool-versions +1 -1
- data/.travis.sh +39 -7
- data/.travis.yml +1 -0
- data/CHANGELOG.md +506 -28
- data/Gemfile +13 -6
- data/README.md +50 -42
- data/kind.gemspec +3 -3
- data/lib/kind.rb +2 -60
- data/lib/kind/__lib__/action_steps.rb +57 -0
- data/lib/kind/__lib__/attributes.rb +66 -0
- data/lib/kind/__lib__/kind.rb +51 -0
- data/lib/kind/__lib__/of.rb +17 -0
- data/lib/kind/__lib__/strict.rb +49 -0
- data/lib/kind/__lib__/undefined.rb +14 -0
- data/lib/kind/action.rb +127 -0
- data/lib/kind/active_model/validation.rb +3 -4
- data/lib/kind/basic.rb +79 -0
- data/lib/kind/basic/error.rb +29 -0
- data/lib/kind/{undefined.rb → basic/undefined.rb} +6 -1
- data/lib/kind/dig.rb +21 -5
- data/lib/kind/either.rb +30 -0
- data/lib/kind/either/left.rb +29 -0
- data/lib/kind/either/methods.rb +17 -0
- data/lib/kind/either/monad.rb +65 -0
- data/lib/kind/either/monad/wrapper.rb +19 -0
- data/lib/kind/either/right.rb +38 -0
- data/lib/kind/empty.rb +2 -0
- data/lib/kind/enum.rb +63 -0
- data/lib/kind/enum/item.rb +40 -0
- data/lib/kind/enum/methods.rb +72 -0
- data/lib/kind/function.rb +45 -0
- data/lib/kind/functional.rb +89 -0
- data/lib/kind/functional/action.rb +87 -0
- data/lib/kind/functional/steps.rb +22 -0
- data/lib/kind/immutable_attributes.rb +34 -0
- data/lib/kind/immutable_attributes/initializer.rb +70 -0
- data/lib/kind/immutable_attributes/reader.rb +38 -0
- data/lib/kind/maybe.rb +37 -12
- data/lib/kind/maybe/methods.rb +21 -0
- data/lib/kind/maybe/monad.rb +82 -0
- data/lib/kind/maybe/monad/wrapper.rb +19 -0
- data/lib/kind/maybe/none.rb +12 -19
- data/lib/kind/maybe/some.rb +68 -26
- data/lib/kind/maybe/typed.rb +11 -5
- data/lib/kind/maybe/{wrappable.rb → wrapper.rb} +8 -4
- data/lib/kind/monad.rb +22 -0
- data/lib/kind/monads.rb +5 -0
- data/lib/kind/objects.rb +17 -0
- data/lib/kind/objects/basic_object.rb +43 -0
- data/lib/kind/objects/modules.rb +32 -0
- data/lib/kind/{type_checkers → objects/modules}/core/array.rb +3 -1
- data/lib/kind/{type_checkers → objects/modules}/core/class.rb +1 -1
- data/lib/kind/{type_checkers → objects/modules}/core/comparable.rb +1 -1
- data/lib/kind/{type_checkers → objects/modules}/core/enumerable.rb +1 -1
- data/lib/kind/{type_checkers → objects/modules}/core/enumerator.rb +1 -1
- data/lib/kind/{type_checkers → objects/modules}/core/file.rb +1 -1
- data/lib/kind/{type_checkers → objects/modules}/core/float.rb +1 -1
- data/lib/kind/{type_checkers → objects/modules}/core/hash.rb +3 -1
- data/lib/kind/{type_checkers → objects/modules}/core/integer.rb +1 -1
- data/lib/kind/{type_checkers → objects/modules}/core/io.rb +1 -1
- data/lib/kind/{type_checkers → objects/modules}/core/method.rb +1 -1
- data/lib/kind/{type_checkers → objects/modules}/core/module.rb +1 -1
- data/lib/kind/{type_checkers → objects/modules}/core/numeric.rb +1 -1
- data/lib/kind/{type_checkers → objects/modules}/core/proc.rb +1 -1
- data/lib/kind/{type_checkers → objects/modules}/core/queue.rb +1 -1
- data/lib/kind/{type_checkers → objects/modules}/core/range.rb +1 -1
- data/lib/kind/{type_checkers → objects/modules}/core/regexp.rb +1 -1
- data/lib/kind/{type_checkers → objects/modules}/core/string.rb +3 -1
- data/lib/kind/{type_checkers → objects/modules}/core/struct.rb +1 -1
- data/lib/kind/{type_checkers → objects/modules}/core/symbol.rb +1 -1
- data/lib/kind/{type_checkers → objects/modules}/core/time.rb +1 -1
- data/lib/kind/{type_checkers → objects/modules}/custom/boolean.rb +2 -2
- data/lib/kind/{type_checkers → objects/modules}/custom/callable.rb +1 -1
- data/lib/kind/{type_checkers → objects/modules}/custom/lambda.rb +1 -1
- data/lib/kind/{type_checkers → objects/modules}/stdlib/open_struct.rb +3 -1
- data/lib/kind/{type_checkers → objects/modules}/stdlib/set.rb +3 -1
- data/lib/kind/objects/nil.rb +17 -0
- data/lib/kind/objects/not_nil.rb +9 -0
- data/lib/kind/objects/object.rb +56 -0
- data/lib/kind/objects/respond_to.rb +30 -0
- data/lib/kind/objects/union_type.rb +44 -0
- data/lib/kind/presence.rb +4 -2
- data/lib/kind/result.rb +31 -0
- data/lib/kind/result/abstract.rb +53 -0
- data/lib/kind/result/failure.rb +33 -0
- data/lib/kind/result/methods.rb +17 -0
- data/lib/kind/result/monad.rb +74 -0
- data/lib/kind/result/monad/wrapper.rb +19 -0
- data/lib/kind/result/success.rb +53 -0
- data/lib/kind/strict/disabled.rb +34 -0
- data/lib/kind/try.rb +22 -10
- data/lib/kind/validator.rb +111 -0
- data/lib/kind/version.rb +1 -1
- metadata +83 -42
- data/lib/kind/active_model/kind_validator.rb +0 -103
- data/lib/kind/core.rb +0 -8
- data/lib/kind/core/kind.rb +0 -61
- data/lib/kind/core/undefined.rb +0 -7
- data/lib/kind/error.rb +0 -15
- data/lib/kind/maybe/result.rb +0 -51
- data/lib/kind/type_checker.rb +0 -87
- data/lib/kind/type_checkers.rb +0 -30
data/Gemfile
CHANGED
@@ -18,24 +18,31 @@ activemodel = case activemodel_version
|
|
18
18
|
|
19
19
|
simplecov_version =
|
20
20
|
case RUBY_VERSION
|
21
|
-
when /\A2.[
|
21
|
+
when /\A2.[123]/ then '0.17.1'
|
22
22
|
when /\A2.4/ then '~> 0.18.5'
|
23
23
|
else '~> 0.19'
|
24
24
|
end
|
25
25
|
|
26
|
+
is_ruby_2_1 = RUBY_VERSION <= '2.2.0'
|
27
|
+
|
28
|
+
minitest_version =
|
29
|
+
if activemodel_version
|
30
|
+
activemodel_version < '4.1' ? '~> 4.2' : '~> 5.0'
|
31
|
+
else
|
32
|
+
is_ruby_2_1 ? '~> 4.2' : '~> 5.0'
|
33
|
+
end
|
34
|
+
|
26
35
|
group :test do
|
27
36
|
if activemodel_version
|
28
37
|
gem 'activesupport', activemodel, require: false
|
29
|
-
gem 'activemodel', activemodel, require: false
|
30
|
-
gem 'minitest', activemodel_version < '4.1' ? '~> 4.2' : '~> 5.0'
|
31
|
-
else
|
32
|
-
gem 'minitest', '~> 5.0'
|
38
|
+
gem 'activemodel' , activemodel, require: false
|
33
39
|
end
|
34
40
|
|
41
|
+
gem 'minitest' , minitest_version
|
35
42
|
gem 'simplecov', simplecov_version, require: false
|
36
43
|
end
|
37
44
|
|
38
|
-
gem 'rake', '~> 13.0'
|
45
|
+
gem 'rake', is_ruby_2_1 ? '~> 12.3' : '~> 13.0'
|
39
46
|
|
40
47
|
# Specify your gem's dependencies in type_validator.gemspec
|
41
48
|
gemspec
|
data/README.md
CHANGED
@@ -1,12 +1,9 @@
|
|
1
1
|
<p align="center">
|
2
2
|
<h1 align="center">🤷 kind</h1>
|
3
|
-
<p align="center"><i>A
|
4
|
-
<br>
|
3
|
+
<p align="center"><i>A development toolkit for Ruby with several small/cohesive abstractions to empower your development workflow - It's totally free of dependencies.</i></p>
|
5
4
|
</p>
|
6
5
|
|
7
6
|
<p align="center">
|
8
|
-
<img src="https://img.shields.io/badge/ruby->%3D%202.2.0-ruby.svg?colorA=99004d&colorB=cc0066" alt="Ruby">
|
9
|
-
|
10
7
|
<a href="https://rubygems.org/gems/kind">
|
11
8
|
<img alt="Gem" src="https://img.shields.io/gem/v/kind.svg?style=flat-square">
|
12
9
|
</a>
|
@@ -15,6 +12,14 @@
|
|
15
12
|
<img alt="Build Status" src="https://travis-ci.com/serradura/kind.svg?branch=master">
|
16
13
|
</a>
|
17
14
|
|
15
|
+
<br />
|
16
|
+
|
17
|
+
<img src="https://img.shields.io/badge/ruby%20%3E=%202.1,%20%3C%203.1-ruby.svg?colorA=99004d&colorB=cc0066" alt="Ruby">
|
18
|
+
|
19
|
+
<img src="https://img.shields.io/badge/rails%20%3E=%203.2.0,%20%3C%207.0-rails.svg?colorA=8B0000&colorB=FF0000" alt="Rails">
|
20
|
+
|
21
|
+
<br />
|
22
|
+
|
18
23
|
<a href="https://codeclimate.com/github/serradura/kind/maintainability">
|
19
24
|
<img alt="Maintainability" src="https://api.codeclimate.com/v1/badges/711329decb2806ccac95/maintainability">
|
20
25
|
</a>
|
@@ -26,20 +31,22 @@
|
|
26
31
|
|
27
32
|
**Motivation:**
|
28
33
|
|
29
|
-
|
34
|
+
This project was born to help me with a simple task, create a light and fast type checker (at runtime) for Ruby. The initial idea was to have something to raise an exception when a method or function (procs) received a wrong input.
|
35
|
+
|
36
|
+
But through time it was natural the addition of more features to improve the development workflow, like monads ([`Kind::Maybe`](#kindmaybe), `Kind::Either` / `Kind::Result`), enums (`Kind::Enum`), immutable objects (`Kind::ImmutableAttributes`), [type validation via ActiveModel::Validation](#kindvalidator-activemodelvalidations), and several abstractions to help the implementation of business logic (`Kind::Functional::Steps`, `Kind::Functional::Action`, `Kind::Action`).
|
30
37
|
|
31
|
-
|
38
|
+
So, I invite you to check out these features to see how they could be useful for you. Enjoy!
|
32
39
|
|
33
40
|
## Documentation <!-- omit in toc -->
|
34
41
|
|
35
42
|
Version | Documentation
|
36
43
|
---------- | -------------
|
37
|
-
unreleased | https://github.com/serradura/
|
38
|
-
5.
|
39
|
-
4.1.0 | https://github.com/serradura/
|
40
|
-
3.1.0 | https://github.com/serradura/
|
41
|
-
2.3.0 | https://github.com/serradura/
|
42
|
-
1.9.0 | https://github.com/serradura/
|
44
|
+
unreleased | https://github.com/serradura/kind/blob/main/README.md
|
45
|
+
5.4.1 | https://github.com/serradura/kind/blob/v5.x/README.md
|
46
|
+
4.1.0 | https://github.com/serradura/kind/blob/v4.x/README.md
|
47
|
+
3.1.0 | https://github.com/serradura/kind/blob/v3.x/README.md
|
48
|
+
2.3.0 | https://github.com/serradura/kind/blob/v2.x/README.md
|
49
|
+
1.9.0 | https://github.com/serradura/kind/blob/v1.x/README.md
|
43
50
|
|
44
51
|
## Table of Contents <!-- omit in toc -->
|
45
52
|
- [Compatibility](#compatibility)
|
@@ -54,16 +61,16 @@ unreleased | https://github.com/serradura/u-case/blob/main/README.md
|
|
54
61
|
- [Kind::\<Type\>.value()](#kindtypevalue-1)
|
55
62
|
- [Kind::\<Type\>.maybe](#kindtypemaybe)
|
56
63
|
- [Kind::\<Type\>?](#kindtype-2)
|
57
|
-
- [Kind::{Array,Hash,String,Set}.
|
58
|
-
- [List of all type
|
64
|
+
- [Kind::{Array,Hash,String,Set}.empty_or()](#kindarrayhashstringsetempty_or)
|
65
|
+
- [List of all type handlers](#list-of-all-type-handlers)
|
59
66
|
- [Core](#core)
|
60
67
|
- [Stdlib](#stdlib)
|
61
68
|
- [Custom](#custom)
|
62
|
-
- [Creating type
|
69
|
+
- [Creating type handlers](#creating-type-handlers)
|
63
70
|
- [Dynamic creation](#dynamic-creation)
|
64
71
|
- [Using a class or a module](#using-a-class-or-a-module)
|
65
72
|
- [Using an object which responds to ===](#using-an-object-which-responds-to-)
|
66
|
-
- [Kind::<Type>
|
73
|
+
- [Kind::<Type> object](#kindtype-object)
|
67
74
|
- [Utility methods](#utility-methods)
|
68
75
|
- [Kind.of_class?()](#kindof_class)
|
69
76
|
- [Kind.of_module?()](#kindof_module)
|
@@ -115,13 +122,14 @@ unreleased | https://github.com/serradura/u-case/blob/main/README.md
|
|
115
122
|
|
116
123
|
## Compatibility
|
117
124
|
|
118
|
-
|
|
119
|
-
| -------------- | ------- |
|
120
|
-
| unreleased | main | >= 2.
|
121
|
-
| 4.1
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
+
| kind | branch | ruby | activemodel |
|
126
|
+
| -------------- | ------- | ------------------ | -------------- |
|
127
|
+
| unreleased | main | >= 2.1.0, <= 3.0.0 | >= 3.2, < 7.0 |
|
128
|
+
| 5.4.1 | v5.x | >= 2.1.0, <= 3.0.0 | >= 3.2, < 7.0 |
|
129
|
+
| 4.1.0 | v4.x | >= 2.2.0, <= 3.0.0 | >= 3.2, < 7.0 |
|
130
|
+
| 3.1.0 | v3.x | >= 2.2.0, <= 2.7 | >= 3.2, < 7.0 |
|
131
|
+
| 2.3.0 | v2.x | >= 2.2.0, <= 2.7 | >= 3.2, <= 6.0 |
|
132
|
+
| 1.9.0 | v1.x | >= 2.2.0, <= 2.7 | >= 3.2, <= 6.0 |
|
125
133
|
|
126
134
|
> Note: The activemodel is an optional dependency, it is related with the [Kind::Validator](#kindvalidator-activemodelvalidations).
|
127
135
|
|
@@ -322,17 +330,17 @@ collection.select(&Kind::Enumerable?) # [{:number=>1}, {:number=>3}, [:number, 5
|
|
322
330
|
|
323
331
|
[⬆️ Back to Top](#table-of-contents-)
|
324
332
|
|
325
|
-
### Kind::{Array,Hash,String,Set}.
|
333
|
+
### Kind::{Array,Hash,String,Set}.empty_or()
|
326
334
|
|
327
|
-
This method is available for some type
|
335
|
+
This method is available for some type handlers (`Kind::Array`, `Kind::Hash`, `Kind::String`, `Kind::Set`), and it will return an empty frozen value if the given one hasn't the expected kind.
|
328
336
|
```ruby
|
329
|
-
Kind::Array.
|
330
|
-
Kind::Array.
|
337
|
+
Kind::Array.empty_or({}) # []
|
338
|
+
Kind::Array.empty_or({}).frozen? # true
|
331
339
|
```
|
332
340
|
|
333
341
|
[⬆️ Back to Top](#table-of-contents-)
|
334
342
|
|
335
|
-
### List of all type
|
343
|
+
### List of all type handlers
|
336
344
|
|
337
345
|
#### Core
|
338
346
|
|
@@ -371,9 +379,9 @@ Kind::Array.value_or_empty({}).frozen? # true
|
|
371
379
|
|
372
380
|
[⬆️ Back to Top](#table-of-contents-)
|
373
381
|
|
374
|
-
### Creating type
|
382
|
+
### Creating type handlers
|
375
383
|
|
376
|
-
There are two ways to do this, you can create type
|
384
|
+
There are two ways to do this, you can create type handlers dynamically or defining a module.
|
377
385
|
|
378
386
|
#### Dynamic creation
|
379
387
|
|
@@ -389,7 +397,7 @@ kind_of_user = Kind::Of(User)
|
|
389
397
|
|
390
398
|
# kind_of_user.name
|
391
399
|
# kind_of_user.kind
|
392
|
-
# The type
|
400
|
+
# The type handler can return its kind and its name
|
393
401
|
kind_of_user.name # "User"
|
394
402
|
kind_of_user.kind # User
|
395
403
|
|
@@ -459,7 +467,7 @@ PositiveInteger = Kind::Of(
|
|
459
467
|
|
460
468
|
# PositiveInteger.name
|
461
469
|
# PositiveInteger.kind
|
462
|
-
# The type
|
470
|
+
# The type handler can return its kind and its name
|
463
471
|
PositiveInteger.name # "PositiveInteger"
|
464
472
|
PositiveInteger.kind # #<Proc:0x0000.... >
|
465
473
|
|
@@ -520,9 +528,9 @@ PositiveInteger.maybe(2).value_or(1) # 2
|
|
520
528
|
|
521
529
|
[⬆️ Back to Top](#table-of-contents-)
|
522
530
|
|
523
|
-
#### Kind::<Type>
|
531
|
+
#### Kind::<Type> object
|
524
532
|
|
525
|
-
The idea here is to create a type
|
533
|
+
The idea here is to create a type handler inside of the `Kind` namespace and to do this you will only need to use pure Ruby. e.g:
|
526
534
|
|
527
535
|
```ruby
|
528
536
|
class User
|
@@ -530,9 +538,9 @@ end
|
|
530
538
|
|
531
539
|
module Kind
|
532
540
|
module User
|
533
|
-
extend self,
|
541
|
+
extend self, ::Kind::Object
|
534
542
|
|
535
|
-
# Define the expected kind of this type
|
543
|
+
# Define the expected kind of this type handler.
|
536
544
|
def kind; ::User; end
|
537
545
|
end
|
538
546
|
|
@@ -542,7 +550,7 @@ module Kind
|
|
542
550
|
end
|
543
551
|
end
|
544
552
|
|
545
|
-
# Doing this you will have the same methods of a standard type
|
553
|
+
# Doing this you will have the same methods of a standard type handler (like: `Kind::Symbol`).
|
546
554
|
|
547
555
|
user = User.new
|
548
556
|
|
@@ -560,7 +568,7 @@ The advantages of this approach are:
|
|
560
568
|
|
561
569
|
The disadvantage is:
|
562
570
|
|
563
|
-
1. You could overwrite some standard type
|
571
|
+
1. You could overwrite some standard type handler or constant. I believe that this will be hard to happen, but must be your concern if you decide to use this kind of approach.
|
564
572
|
|
565
573
|
[⬆️ Back to Top](#table-of-contents-)
|
566
574
|
|
@@ -1454,7 +1462,7 @@ Follows the list of constants if the alias was defined:
|
|
1454
1462
|
|
1455
1463
|
## Kind::Validator (ActiveModel::Validations)
|
1456
1464
|
|
1457
|
-
This module enables the capability to validate types via [`ActiveModel::Validations >= 3.2, <
|
1465
|
+
This module enables the capability to validate types via [`ActiveModel::Validations >= 3.2, < 7.0`](https://api.rubyonrails.org/classes/ActiveModel/Validations.html). e.g
|
1458
1466
|
|
1459
1467
|
```ruby
|
1460
1468
|
class Person
|
@@ -1470,10 +1478,10 @@ And to make use of it, you will need to do an explicitly require. e.g:
|
|
1470
1478
|
|
1471
1479
|
```ruby
|
1472
1480
|
# In some Gemfile
|
1473
|
-
gem 'kind', require: 'kind/
|
1481
|
+
gem 'kind', require: 'kind/validator'
|
1474
1482
|
|
1475
1483
|
# In some .rb file
|
1476
|
-
require 'kind/
|
1484
|
+
require 'kind/validator'
|
1477
1485
|
```
|
1478
1486
|
|
1479
1487
|
[⬆️ Back to Top](#table-of-contents-)
|
@@ -1492,7 +1500,7 @@ Use an array to verify if the attribute is an instance of one of the classes/mod
|
|
1492
1500
|
validates :status, kind: { of: [String, Symbol]}
|
1493
1501
|
```
|
1494
1502
|
|
1495
|
-
Because of kind verification be made via `===` you can use type
|
1503
|
+
Because of kind verification be made via `===` you can use type handlers as the expected kinds.
|
1496
1504
|
|
1497
1505
|
```ruby
|
1498
1506
|
validates :alive, kind: Kind::Boolean
|
data/kind.gemspec
CHANGED
@@ -6,11 +6,11 @@ Gem::Specification.new do |spec|
|
|
6
6
|
spec.authors = ['Rodrigo Serradura']
|
7
7
|
spec.email = ['rodrigo.serradura@gmail.com']
|
8
8
|
|
9
|
-
spec.summary = %q{A
|
10
|
-
spec.description = %q{A
|
9
|
+
spec.summary = %q{A development toolkit for Ruby with several small/cohesive abstractions to empower your development workflow.}
|
10
|
+
spec.description = %q{A development toolkit for Ruby with several small/cohesive abstractions (monads, enums, business logic, data validation...) to empower your development workflow - It's totally free of dependencies.}
|
11
11
|
spec.homepage = 'https://github.com/serradura/kind'
|
12
12
|
spec.license = 'MIT'
|
13
|
-
spec.required_ruby_version = Gem::Requirement.new('>= 2.
|
13
|
+
spec.required_ruby_version = Gem::Requirement.new('>= 2.1.0')
|
14
14
|
|
15
15
|
spec.metadata['homepage_uri'] = spec.homepage
|
16
16
|
spec.metadata['source_code_uri'] = 'https://github.com/serradura/kind'
|
data/lib/kind.rb
CHANGED
@@ -1,62 +1,4 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require '
|
4
|
-
require '
|
5
|
-
|
6
|
-
require 'kind/version'
|
7
|
-
require 'kind/core'
|
8
|
-
|
9
|
-
require 'kind/error'
|
10
|
-
require 'kind/empty'
|
11
|
-
require 'kind/dig'
|
12
|
-
require 'kind/try'
|
13
|
-
require 'kind/presence'
|
14
|
-
require 'kind/undefined'
|
15
|
-
require 'kind/maybe'
|
16
|
-
|
17
|
-
require 'kind/type_checker'
|
18
|
-
require 'kind/type_checkers'
|
19
|
-
|
20
|
-
module Kind
|
21
|
-
extend self
|
22
|
-
|
23
|
-
def is?(kind, arg)
|
24
|
-
KIND.is?(kind, arg)
|
25
|
-
end
|
26
|
-
|
27
|
-
alias is is?
|
28
|
-
|
29
|
-
def of?(kind, *args)
|
30
|
-
KIND.of?(kind, args)
|
31
|
-
end
|
32
|
-
|
33
|
-
def of_class?(value)
|
34
|
-
KIND.of_class?(value)
|
35
|
-
end
|
36
|
-
|
37
|
-
def of_module?(value)
|
38
|
-
KIND.of_module?(value)
|
39
|
-
end
|
40
|
-
|
41
|
-
def respond_to(value, *method_names)
|
42
|
-
method_names.each { |method_name| KIND.respond_to!(method_name, value) }
|
43
|
-
|
44
|
-
value
|
45
|
-
end
|
46
|
-
|
47
|
-
def of_module_or_class(value)
|
48
|
-
KIND.of_module_or_class!(value)
|
49
|
-
end
|
50
|
-
|
51
|
-
def of(kind, object)
|
52
|
-
KIND.of!(kind, object)
|
53
|
-
end
|
54
|
-
|
55
|
-
def value(kind, value, default:)
|
56
|
-
KIND.value(kind, value, of(kind, default))
|
57
|
-
end
|
58
|
-
|
59
|
-
def Of(kind, opt = Empty::HASH)
|
60
|
-
TypeChecker::Object.new(kind, opt)
|
61
|
-
end
|
62
|
-
end
|
3
|
+
require 'kind/basic'
|
4
|
+
require 'kind/objects'
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Kind
|
4
|
+
module ACTION_STEPS
|
5
|
+
private
|
6
|
+
|
7
|
+
def Check(mthod); ->(value) { __Check(thod, value) }; end
|
8
|
+
def Step(mthod); ->(value) { __Step(mthod, value) }; end
|
9
|
+
def Map(mthod); ->(value) { __Map(mthod, value) }; end
|
10
|
+
def Tee(mthod); ->(value) { __Tee(mthod, value) }; end
|
11
|
+
def Try(mthod, opt = Empty::HASH)
|
12
|
+
->(value) { __Try(mthod, value, opt) }
|
13
|
+
end
|
14
|
+
|
15
|
+
def Check!(mthod, value); __Check(mthod, value); end
|
16
|
+
def Step!(mthod, value); __Step(mthod, value); end
|
17
|
+
def Map!(mthod, value); __Map(mthod, value); end
|
18
|
+
def Tee!(mthod, value); __Tee(mthod, value); end
|
19
|
+
def Try!(mthod, value, opt = Empty::HASH); __Try(mthod, value, opt); end
|
20
|
+
|
21
|
+
def __Check(mthod, value) # :nodoc:
|
22
|
+
__resolve_step(mthod, value) ? Success(mthod, value) : Failure(mthod, value)
|
23
|
+
end
|
24
|
+
|
25
|
+
def __Step(mthod, value) # :nodoc:
|
26
|
+
__resolve_step(mthod, value)
|
27
|
+
end
|
28
|
+
|
29
|
+
def __Map(mthod, value) # :nodoc:
|
30
|
+
Success(mthod, __resolve_step(mthod, value))
|
31
|
+
end
|
32
|
+
|
33
|
+
def __Tee(mthod, value) # :nodoc:
|
34
|
+
__resolve_step(mthod, value)
|
35
|
+
|
36
|
+
Success(mthod, value)
|
37
|
+
end
|
38
|
+
|
39
|
+
def __Try(mthod, value, opt = Empty::HASH) # :nodoc:
|
40
|
+
begin
|
41
|
+
Success(mthod, __resolve_step(mthod, value))
|
42
|
+
rescue opt.fetch(:catch, StandardError) => e
|
43
|
+
Failure(mthod, __map_step_exception(e))
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def __resolve_step(mthod, value) # :nodoc:
|
48
|
+
send(mthod, value)
|
49
|
+
end
|
50
|
+
|
51
|
+
def __map_step_exception(value) # :nodoc:
|
52
|
+
value
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
private_constant :ACTION_STEPS
|
57
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'kind/__lib__/kind'
|
4
|
+
require 'kind/__lib__/undefined'
|
5
|
+
|
6
|
+
module Kind
|
7
|
+
module ATTRIBUTES
|
8
|
+
extend self
|
9
|
+
|
10
|
+
def name!(name)
|
11
|
+
STRICT.kind_of(::Symbol, name)
|
12
|
+
end
|
13
|
+
|
14
|
+
def value(kind, default, visibility = :private)
|
15
|
+
[kind, default, visibility]
|
16
|
+
end
|
17
|
+
|
18
|
+
def value_to_assign(kind, default, hash, name)
|
19
|
+
raw_value = hash[name]
|
20
|
+
|
21
|
+
return raw_value if kind.nil? && UNDEFINED == default
|
22
|
+
|
23
|
+
value = resolve_value_to_assign(kind, default, raw_value)
|
24
|
+
|
25
|
+
(kind.nil? || kind === value) ? value : nil
|
26
|
+
end
|
27
|
+
|
28
|
+
def value!(kind, default)
|
29
|
+
return value(kind, default) unless kind.nil?
|
30
|
+
|
31
|
+
raise Error.new("kind expected to not be nil")
|
32
|
+
end
|
33
|
+
|
34
|
+
def value_to_assign!(kind, default, hash, name)
|
35
|
+
value = resolve_value_to_assign(kind, default, hash[name])
|
36
|
+
|
37
|
+
Kind.of(kind, value, label: name)
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def resolve_value_to_assign(kind, default, value)
|
43
|
+
if kind == ::Proc
|
44
|
+
UNDEFINED == default ? value : KIND.value(kind, value, default)
|
45
|
+
else
|
46
|
+
default_is_a_callable = default.respond_to?(:call)
|
47
|
+
|
48
|
+
default_value =
|
49
|
+
if default_is_a_callable
|
50
|
+
default_fn = Proc === default ? default : default.method(:call)
|
51
|
+
|
52
|
+
default_fn.arity != 0 ? default_fn.call(value) : default_fn.call
|
53
|
+
else
|
54
|
+
default
|
55
|
+
end
|
56
|
+
|
57
|
+
return value if UNDEFINED == default_value
|
58
|
+
return default_value || value if kind.nil?
|
59
|
+
|
60
|
+
default_is_a_callable ? KIND.value(kind, default_value, value) : KIND.value(kind, value, default_value)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
private_constant :ATTRIBUTES
|
66
|
+
end
|