kind 5.1.0 → 5.5.0
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 +37 -10
- data/CHANGELOG.md +518 -29
- data/README.md +48 -45
- data/kind.gemspec +2 -2
- data/lib/kind.rb +2 -49
- 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 +1 -1
- data/lib/kind/basic.rb +83 -0
- data/lib/kind/basic/error.rb +29 -0
- data/lib/kind/{core → basic}/undefined.rb +6 -1
- data/lib/kind/{core/dig.rb → 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/{core/empty.rb → empty.rb} +2 -0
- data/lib/kind/{core/empty → empty}/constant.rb +0 -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 +69 -0
- 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 +50 -0
- data/lib/kind/maybe/some.rb +132 -0
- data/lib/kind/maybe/typed.rb +35 -0
- data/lib/kind/{core/maybe/wrappable.rb → maybe/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/{core/type_checkers/ruby → objects/modules/core}/array.rb +3 -1
- data/lib/kind/{core/type_checkers/ruby → objects/modules/core}/class.rb +1 -1
- data/lib/kind/{core/type_checkers/ruby → objects/modules/core}/comparable.rb +1 -1
- data/lib/kind/{core/type_checkers/ruby → objects/modules/core}/enumerable.rb +1 -1
- data/lib/kind/{core/type_checkers/ruby → objects/modules/core}/enumerator.rb +1 -1
- data/lib/kind/{core/type_checkers/ruby → objects/modules/core}/file.rb +1 -1
- data/lib/kind/{core/type_checkers/ruby → objects/modules/core}/float.rb +1 -1
- data/lib/kind/{core/type_checkers/ruby → objects/modules/core}/hash.rb +3 -1
- data/lib/kind/{core/type_checkers/ruby → objects/modules/core}/integer.rb +1 -1
- data/lib/kind/{core/type_checkers/ruby → objects/modules/core}/io.rb +1 -1
- data/lib/kind/{core/type_checkers/ruby → objects/modules/core}/method.rb +1 -1
- data/lib/kind/{core/type_checkers/ruby → objects/modules/core}/module.rb +1 -1
- data/lib/kind/{core/type_checkers/ruby → objects/modules/core}/numeric.rb +1 -1
- data/lib/kind/{core/type_checkers/ruby → objects/modules/core}/proc.rb +1 -1
- data/lib/kind/{core/type_checkers/ruby → objects/modules/core}/queue.rb +1 -1
- data/lib/kind/{core/type_checkers/ruby → objects/modules/core}/range.rb +1 -1
- data/lib/kind/{core/type_checkers/ruby → objects/modules/core}/regexp.rb +1 -1
- data/lib/kind/{core/type_checkers/ruby → objects/modules/core}/string.rb +3 -1
- data/lib/kind/{core/type_checkers/ruby → objects/modules/core}/struct.rb +1 -1
- data/lib/kind/{core/type_checkers/ruby → objects/modules/core}/symbol.rb +1 -1
- data/lib/kind/{core/type_checkers/ruby → objects/modules/core}/time.rb +1 -1
- data/lib/kind/{core/type_checkers → objects/modules}/custom/boolean.rb +2 -2
- data/lib/kind/{core/type_checkers → objects/modules}/custom/callable.rb +1 -1
- data/lib/kind/{core/type_checkers → objects/modules}/custom/lambda.rb +1 -1
- data/lib/kind/{core/type_checkers → objects/modules}/stdlib/open_struct.rb +3 -1
- data/lib/kind/{core/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/{core/presence.rb → 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 +46 -0
- data/lib/kind/validator.rb +14 -10
- data/lib/kind/version.rb +1 -1
- metadata +91 -49
- data/lib/kind/core.rb +0 -15
- data/lib/kind/core/error.rb +0 -15
- data/lib/kind/core/maybe.rb +0 -42
- data/lib/kind/core/maybe/none.rb +0 -57
- data/lib/kind/core/maybe/result.rb +0 -51
- data/lib/kind/core/maybe/some.rb +0 -90
- data/lib/kind/core/maybe/typed.rb +0 -29
- data/lib/kind/core/try.rb +0 -34
- data/lib/kind/core/type_checker.rb +0 -87
- data/lib/kind/core/type_checkers.rb +0 -30
- data/lib/kind/core/utils/kind.rb +0 -61
- data/lib/kind/core/utils/undefined.rb +0 -7
data/README.md
CHANGED
@@ -1,7 +1,6 @@
|
|
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">
|
@@ -9,16 +8,18 @@
|
|
9
8
|
<img alt="Gem" src="https://img.shields.io/gem/v/kind.svg?style=flat-square">
|
10
9
|
</a>
|
11
10
|
|
12
|
-
<img src="https://img.shields.io/badge/ruby%20%3E=%202.1.0,%20%3C%203.1-ruby.svg?colorA=99004d&colorB=cc0066" alt="Ruby">
|
13
|
-
|
14
|
-
<img src="https://img.shields.io/badge/rails%20%3E=%203.2.0,%20%3C%207-rails.svg?colorA=8B0000&colorB=FF0000" alt="Rails">
|
15
|
-
|
16
|
-
<br />
|
17
|
-
|
18
11
|
<a href="https://travis-ci.com/serradura/kind">
|
19
12
|
<img alt="Build Status" src="https://travis-ci.com/serradura/kind.svg?branch=master">
|
20
13
|
</a>
|
21
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
|
+
|
22
23
|
<a href="https://codeclimate.com/github/serradura/kind/maintainability">
|
23
24
|
<img alt="Maintainability" src="https://api.codeclimate.com/v1/badges/711329decb2806ccac95/maintainability">
|
24
25
|
</a>
|
@@ -30,20 +31,22 @@
|
|
30
31
|
|
31
32
|
**Motivation:**
|
32
33
|
|
33
|
-
|
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`).
|
34
37
|
|
35
|
-
|
38
|
+
So, I invite you to check out these features to see how they could be useful for you. Enjoy!
|
36
39
|
|
37
40
|
## Documentation <!-- omit in toc -->
|
38
41
|
|
39
42
|
Version | Documentation
|
40
43
|
---------- | -------------
|
41
|
-
unreleased | https://github.com/serradura/
|
42
|
-
5.
|
43
|
-
4.1.0 | https://github.com/serradura/
|
44
|
-
3.1.0 | https://github.com/serradura/
|
45
|
-
2.3.0 | https://github.com/serradura/
|
46
|
-
1.9.0 | https://github.com/serradura/
|
44
|
+
unreleased | https://github.com/serradura/kind/blob/main/README.md
|
45
|
+
5.5.0 | 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
|
47
50
|
|
48
51
|
## Table of Contents <!-- omit in toc -->
|
49
52
|
- [Compatibility](#compatibility)
|
@@ -58,16 +61,16 @@ unreleased | https://github.com/serradura/u-case/blob/main/README.md
|
|
58
61
|
- [Kind::\<Type\>.value()](#kindtypevalue-1)
|
59
62
|
- [Kind::\<Type\>.maybe](#kindtypemaybe)
|
60
63
|
- [Kind::\<Type\>?](#kindtype-2)
|
61
|
-
- [Kind::{Array,Hash,String,Set}.
|
62
|
-
- [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)
|
63
66
|
- [Core](#core)
|
64
67
|
- [Stdlib](#stdlib)
|
65
68
|
- [Custom](#custom)
|
66
|
-
- [Creating type
|
69
|
+
- [Creating type handlers](#creating-type-handlers)
|
67
70
|
- [Dynamic creation](#dynamic-creation)
|
68
71
|
- [Using a class or a module](#using-a-class-or-a-module)
|
69
72
|
- [Using an object which responds to ===](#using-an-object-which-responds-to-)
|
70
|
-
- [Kind::<Type>
|
73
|
+
- [Kind::<Type> object](#kindtype-object)
|
71
74
|
- [Utility methods](#utility-methods)
|
72
75
|
- [Kind.of_class?()](#kindof_class)
|
73
76
|
- [Kind.of_module?()](#kindof_module)
|
@@ -119,14 +122,14 @@ unreleased | https://github.com/serradura/u-case/blob/main/README.md
|
|
119
122
|
|
120
123
|
## Compatibility
|
121
124
|
|
122
|
-
|
|
123
|
-
| -------------- | ------- |
|
124
|
-
| unreleased | main | >= 2.1.0 | >= 3.2,
|
125
|
-
| 5.
|
126
|
-
| 4.1.0 | v4.x | >= 2.2.0 | >= 3.2,
|
127
|
-
| 3.1.0 | v3.x | >= 2.2.0 | >= 3.2,
|
128
|
-
| 2.3.0 | v2.x | >= 2.2.0 | >= 3.2, <= 6.0 |
|
129
|
-
| 1.9.0 | v1.x | >= 2.2.0 | >= 3.2, <= 6.0 |
|
125
|
+
| kind | branch | ruby | activemodel |
|
126
|
+
| -------------- | ------- | ------------------ | -------------- |
|
127
|
+
| unreleased | main | >= 2.1.0, <= 3.0.0 | >= 3.2, < 7.0 |
|
128
|
+
| 5.5.0 | 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 |
|
130
133
|
|
131
134
|
> Note: The activemodel is an optional dependency, it is related with the [Kind::Validator](#kindvalidator-activemodelvalidations).
|
132
135
|
|
@@ -327,17 +330,17 @@ collection.select(&Kind::Enumerable?) # [{:number=>1}, {:number=>3}, [:number, 5
|
|
327
330
|
|
328
331
|
[⬆️ Back to Top](#table-of-contents-)
|
329
332
|
|
330
|
-
### Kind::{Array,Hash,String,Set}.
|
333
|
+
### Kind::{Array,Hash,String,Set}.empty_or()
|
331
334
|
|
332
|
-
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.
|
333
336
|
```ruby
|
334
|
-
Kind::Array.
|
335
|
-
Kind::Array.
|
337
|
+
Kind::Array.empty_or({}) # []
|
338
|
+
Kind::Array.empty_or({}).frozen? # true
|
336
339
|
```
|
337
340
|
|
338
341
|
[⬆️ Back to Top](#table-of-contents-)
|
339
342
|
|
340
|
-
### List of all type
|
343
|
+
### List of all type handlers
|
341
344
|
|
342
345
|
#### Core
|
343
346
|
|
@@ -376,9 +379,9 @@ Kind::Array.value_or_empty({}).frozen? # true
|
|
376
379
|
|
377
380
|
[⬆️ Back to Top](#table-of-contents-)
|
378
381
|
|
379
|
-
### Creating type
|
382
|
+
### Creating type handlers
|
380
383
|
|
381
|
-
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.
|
382
385
|
|
383
386
|
#### Dynamic creation
|
384
387
|
|
@@ -394,7 +397,7 @@ kind_of_user = Kind::Of(User)
|
|
394
397
|
|
395
398
|
# kind_of_user.name
|
396
399
|
# kind_of_user.kind
|
397
|
-
# The type
|
400
|
+
# The type handler can return its kind and its name
|
398
401
|
kind_of_user.name # "User"
|
399
402
|
kind_of_user.kind # User
|
400
403
|
|
@@ -464,7 +467,7 @@ PositiveInteger = Kind::Of(
|
|
464
467
|
|
465
468
|
# PositiveInteger.name
|
466
469
|
# PositiveInteger.kind
|
467
|
-
# The type
|
470
|
+
# The type handler can return its kind and its name
|
468
471
|
PositiveInteger.name # "PositiveInteger"
|
469
472
|
PositiveInteger.kind # #<Proc:0x0000.... >
|
470
473
|
|
@@ -525,9 +528,9 @@ PositiveInteger.maybe(2).value_or(1) # 2
|
|
525
528
|
|
526
529
|
[⬆️ Back to Top](#table-of-contents-)
|
527
530
|
|
528
|
-
#### Kind::<Type>
|
531
|
+
#### Kind::<Type> object
|
529
532
|
|
530
|
-
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:
|
531
534
|
|
532
535
|
```ruby
|
533
536
|
class User
|
@@ -535,9 +538,9 @@ end
|
|
535
538
|
|
536
539
|
module Kind
|
537
540
|
module User
|
538
|
-
extend self,
|
541
|
+
extend self, ::Kind::Object
|
539
542
|
|
540
|
-
# Define the expected kind of this type
|
543
|
+
# Define the expected kind of this type handler.
|
541
544
|
def kind; ::User; end
|
542
545
|
end
|
543
546
|
|
@@ -547,7 +550,7 @@ module Kind
|
|
547
550
|
end
|
548
551
|
end
|
549
552
|
|
550
|
-
# 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`).
|
551
554
|
|
552
555
|
user = User.new
|
553
556
|
|
@@ -565,7 +568,7 @@ The advantages of this approach are:
|
|
565
568
|
|
566
569
|
The disadvantage is:
|
567
570
|
|
568
|
-
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.
|
569
572
|
|
570
573
|
[⬆️ Back to Top](#table-of-contents-)
|
571
574
|
|
@@ -1459,7 +1462,7 @@ Follows the list of constants if the alias was defined:
|
|
1459
1462
|
|
1460
1463
|
## Kind::Validator (ActiveModel::Validations)
|
1461
1464
|
|
1462
|
-
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
|
1463
1466
|
|
1464
1467
|
```ruby
|
1465
1468
|
class Person
|
@@ -1497,7 +1500,7 @@ Use an array to verify if the attribute is an instance of one of the classes/mod
|
|
1497
1500
|
validates :status, kind: { of: [String, Symbol]}
|
1498
1501
|
```
|
1499
1502
|
|
1500
|
-
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.
|
1501
1504
|
|
1502
1505
|
```ruby
|
1503
1506
|
validates :alive, kind: Kind::Boolean
|
data/kind.gemspec
CHANGED
@@ -6,8 +6,8 @@ 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
13
|
spec.required_ruby_version = Gem::Requirement.new('>= 2.1.0')
|
data/lib/kind.rb
CHANGED
@@ -1,51 +1,4 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require '
|
4
|
-
require '
|
5
|
-
|
6
|
-
module Kind
|
7
|
-
require 'kind/version'
|
8
|
-
require 'kind/core'
|
9
|
-
|
10
|
-
extend self
|
11
|
-
|
12
|
-
def is?(kind, arg)
|
13
|
-
KIND.is?(kind, arg)
|
14
|
-
end
|
15
|
-
|
16
|
-
alias is is?
|
17
|
-
|
18
|
-
def of?(kind, *args)
|
19
|
-
KIND.of?(kind, args)
|
20
|
-
end
|
21
|
-
|
22
|
-
def of_class?(value)
|
23
|
-
KIND.of_class?(value)
|
24
|
-
end
|
25
|
-
|
26
|
-
def of_module?(value)
|
27
|
-
KIND.of_module?(value)
|
28
|
-
end
|
29
|
-
|
30
|
-
def respond_to(value, *method_names)
|
31
|
-
method_names.each { |method_name| KIND.respond_to!(method_name, value) }
|
32
|
-
|
33
|
-
value
|
34
|
-
end
|
35
|
-
|
36
|
-
def of_module_or_class(value)
|
37
|
-
KIND.of_module_or_class!(value)
|
38
|
-
end
|
39
|
-
|
40
|
-
def of(kind, object)
|
41
|
-
KIND.of!(kind, object)
|
42
|
-
end
|
43
|
-
|
44
|
-
def value(kind, value, default:)
|
45
|
-
KIND.value(kind, value, of(kind, default))
|
46
|
-
end
|
47
|
-
|
48
|
-
def Of(kind, opt = Empty::HASH)
|
49
|
-
TypeChecker::Object.new(kind, opt)
|
50
|
-
end
|
51
|
-
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
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'kind/__lib__/strict'
|
4
|
+
|
5
|
+
module Kind
|
6
|
+
module KIND
|
7
|
+
extend self
|
8
|
+
|
9
|
+
def nil_or_undefined?(value) # :nodoc:
|
10
|
+
value.nil? || Undefined == value
|
11
|
+
end
|
12
|
+
|
13
|
+
def of?(kind, values) # :nodoc:
|
14
|
+
of_kind = -> value { kind === value }
|
15
|
+
|
16
|
+
values.empty? ? of_kind : values.all?(&of_kind)
|
17
|
+
end
|
18
|
+
|
19
|
+
def respond_to!(method_name, value) # :nodoc:
|
20
|
+
return value if value.respond_to?(method_name)
|
21
|
+
|
22
|
+
raise Error.new("expected #{value} to respond to :#{method_name}")
|
23
|
+
end
|
24
|
+
|
25
|
+
def interface?(method_names, value) # :nodoc:
|
26
|
+
method_names.all? { |method_name| value.respond_to?(method_name) }
|
27
|
+
end
|
28
|
+
|
29
|
+
def value(kind, arg, default) # :nodoc:
|
30
|
+
kind === arg ? arg : default
|
31
|
+
end
|
32
|
+
|
33
|
+
def is?(expected, value) # :nodoc:
|
34
|
+
is(STRICT.module_or_class(expected), value)
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def is(expected_kind, value) # :nodoc:
|
40
|
+
kind = STRICT.module_or_class(value)
|
41
|
+
|
42
|
+
if OF.class?(kind)
|
43
|
+
kind <= expected_kind || expected_kind == ::Class
|
44
|
+
else
|
45
|
+
kind == expected_kind || kind.kind_of?(expected_kind)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
private_constant :KIND
|
51
|
+
end
|