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.
Files changed (103) hide show
  1. checksums.yaml +4 -4
  2. data/.tool-versions +1 -1
  3. data/.travis.sh +39 -7
  4. data/.travis.yml +1 -0
  5. data/CHANGELOG.md +506 -28
  6. data/Gemfile +13 -6
  7. data/README.md +50 -42
  8. data/kind.gemspec +3 -3
  9. data/lib/kind.rb +2 -60
  10. data/lib/kind/__lib__/action_steps.rb +57 -0
  11. data/lib/kind/__lib__/attributes.rb +66 -0
  12. data/lib/kind/__lib__/kind.rb +51 -0
  13. data/lib/kind/__lib__/of.rb +17 -0
  14. data/lib/kind/__lib__/strict.rb +49 -0
  15. data/lib/kind/__lib__/undefined.rb +14 -0
  16. data/lib/kind/action.rb +127 -0
  17. data/lib/kind/active_model/validation.rb +3 -4
  18. data/lib/kind/basic.rb +79 -0
  19. data/lib/kind/basic/error.rb +29 -0
  20. data/lib/kind/{undefined.rb → basic/undefined.rb} +6 -1
  21. data/lib/kind/dig.rb +21 -5
  22. data/lib/kind/either.rb +30 -0
  23. data/lib/kind/either/left.rb +29 -0
  24. data/lib/kind/either/methods.rb +17 -0
  25. data/lib/kind/either/monad.rb +65 -0
  26. data/lib/kind/either/monad/wrapper.rb +19 -0
  27. data/lib/kind/either/right.rb +38 -0
  28. data/lib/kind/empty.rb +2 -0
  29. data/lib/kind/enum.rb +63 -0
  30. data/lib/kind/enum/item.rb +40 -0
  31. data/lib/kind/enum/methods.rb +72 -0
  32. data/lib/kind/function.rb +45 -0
  33. data/lib/kind/functional.rb +89 -0
  34. data/lib/kind/functional/action.rb +87 -0
  35. data/lib/kind/functional/steps.rb +22 -0
  36. data/lib/kind/immutable_attributes.rb +34 -0
  37. data/lib/kind/immutable_attributes/initializer.rb +70 -0
  38. data/lib/kind/immutable_attributes/reader.rb +38 -0
  39. data/lib/kind/maybe.rb +37 -12
  40. data/lib/kind/maybe/methods.rb +21 -0
  41. data/lib/kind/maybe/monad.rb +82 -0
  42. data/lib/kind/maybe/monad/wrapper.rb +19 -0
  43. data/lib/kind/maybe/none.rb +12 -19
  44. data/lib/kind/maybe/some.rb +68 -26
  45. data/lib/kind/maybe/typed.rb +11 -5
  46. data/lib/kind/maybe/{wrappable.rb → wrapper.rb} +8 -4
  47. data/lib/kind/monad.rb +22 -0
  48. data/lib/kind/monads.rb +5 -0
  49. data/lib/kind/objects.rb +17 -0
  50. data/lib/kind/objects/basic_object.rb +43 -0
  51. data/lib/kind/objects/modules.rb +32 -0
  52. data/lib/kind/{type_checkers → objects/modules}/core/array.rb +3 -1
  53. data/lib/kind/{type_checkers → objects/modules}/core/class.rb +1 -1
  54. data/lib/kind/{type_checkers → objects/modules}/core/comparable.rb +1 -1
  55. data/lib/kind/{type_checkers → objects/modules}/core/enumerable.rb +1 -1
  56. data/lib/kind/{type_checkers → objects/modules}/core/enumerator.rb +1 -1
  57. data/lib/kind/{type_checkers → objects/modules}/core/file.rb +1 -1
  58. data/lib/kind/{type_checkers → objects/modules}/core/float.rb +1 -1
  59. data/lib/kind/{type_checkers → objects/modules}/core/hash.rb +3 -1
  60. data/lib/kind/{type_checkers → objects/modules}/core/integer.rb +1 -1
  61. data/lib/kind/{type_checkers → objects/modules}/core/io.rb +1 -1
  62. data/lib/kind/{type_checkers → objects/modules}/core/method.rb +1 -1
  63. data/lib/kind/{type_checkers → objects/modules}/core/module.rb +1 -1
  64. data/lib/kind/{type_checkers → objects/modules}/core/numeric.rb +1 -1
  65. data/lib/kind/{type_checkers → objects/modules}/core/proc.rb +1 -1
  66. data/lib/kind/{type_checkers → objects/modules}/core/queue.rb +1 -1
  67. data/lib/kind/{type_checkers → objects/modules}/core/range.rb +1 -1
  68. data/lib/kind/{type_checkers → objects/modules}/core/regexp.rb +1 -1
  69. data/lib/kind/{type_checkers → objects/modules}/core/string.rb +3 -1
  70. data/lib/kind/{type_checkers → objects/modules}/core/struct.rb +1 -1
  71. data/lib/kind/{type_checkers → objects/modules}/core/symbol.rb +1 -1
  72. data/lib/kind/{type_checkers → objects/modules}/core/time.rb +1 -1
  73. data/lib/kind/{type_checkers → objects/modules}/custom/boolean.rb +2 -2
  74. data/lib/kind/{type_checkers → objects/modules}/custom/callable.rb +1 -1
  75. data/lib/kind/{type_checkers → objects/modules}/custom/lambda.rb +1 -1
  76. data/lib/kind/{type_checkers → objects/modules}/stdlib/open_struct.rb +3 -1
  77. data/lib/kind/{type_checkers → objects/modules}/stdlib/set.rb +3 -1
  78. data/lib/kind/objects/nil.rb +17 -0
  79. data/lib/kind/objects/not_nil.rb +9 -0
  80. data/lib/kind/objects/object.rb +56 -0
  81. data/lib/kind/objects/respond_to.rb +30 -0
  82. data/lib/kind/objects/union_type.rb +44 -0
  83. data/lib/kind/presence.rb +4 -2
  84. data/lib/kind/result.rb +31 -0
  85. data/lib/kind/result/abstract.rb +53 -0
  86. data/lib/kind/result/failure.rb +33 -0
  87. data/lib/kind/result/methods.rb +17 -0
  88. data/lib/kind/result/monad.rb +74 -0
  89. data/lib/kind/result/monad/wrapper.rb +19 -0
  90. data/lib/kind/result/success.rb +53 -0
  91. data/lib/kind/strict/disabled.rb +34 -0
  92. data/lib/kind/try.rb +22 -10
  93. data/lib/kind/validator.rb +111 -0
  94. data/lib/kind/version.rb +1 -1
  95. metadata +83 -42
  96. data/lib/kind/active_model/kind_validator.rb +0 -103
  97. data/lib/kind/core.rb +0 -8
  98. data/lib/kind/core/kind.rb +0 -61
  99. data/lib/kind/core/undefined.rb +0 -7
  100. data/lib/kind/error.rb +0 -15
  101. data/lib/kind/maybe/result.rb +0 -51
  102. data/lib/kind/type_checker.rb +0 -87
  103. 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.[23]/ then '0.17.1'
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 simple type system (at runtime) for Ruby - free of dependencies.</i></p>
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
- As a creator of Ruby gems, I have a common need that I have to handle in many of my projects: type checking of method arguments.
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
- One of the goals of this project is to do simple type checking like `"some string".is_a?(String)`, but, exposing useful abstractions around this. e.g: [Kind.\<Type\> methods](#verifying-the-kind-of-some-object), [active model validations](#kindvalidator-activemodelvalidations), [maybe monad](#kindmaybe).
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/u-case/blob/main/README.md
38
- 5.0.0 | https://github.com/serradura/u-case/blob/v5.x/README.md
39
- 4.1.0 | https://github.com/serradura/u-case/blob/v4.x/README.md
40
- 3.1.0 | https://github.com/serradura/u-case/blob/v3.x/README.md
41
- 2.3.0 | https://github.com/serradura/u-case/blob/v2.x/README.md
42
- 1.9.0 | https://github.com/serradura/u-case/blob/v1.x/README.md
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}.value_or_empty()](#kindarrayhashstringsetvalue_or_empty)
58
- - [List of all type checkers](#list-of-all-type-checkers)
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 checkers](#creating-type-checkers)
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> module](#kindtype-module)
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
- | u-case | branch | ruby | activemodel |
119
- | -------------- | ------- | -------- | -------------- |
120
- | unreleased | main | >= 2.2.0 | >= 3.2, <= 6.1 |
121
- | 4.1.0 | v4.x | >= 2.2.0 | >= 3.2, <= 6.1 |
122
- | 3.1.0 | v3.x | >= 2.2.0 | >= 3.2, <= 6.1 |
123
- | 2.3.0 | v2.x | >= 2.2.0 | >= 3.2, <= 6.0 |
124
- | 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.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
  [⬆️ &nbsp;Back to Top](#table-of-contents-)
324
332
 
325
- ### Kind::{Array,Hash,String,Set}.value_or_empty()
333
+ ### Kind::{Array,Hash,String,Set}.empty_or()
326
334
 
327
- This method is available for some type checkers (`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.
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.value_or_empty({}) # []
330
- Kind::Array.value_or_empty({}).frozen? # true
337
+ Kind::Array.empty_or({}) # []
338
+ Kind::Array.empty_or({}).frozen? # true
331
339
  ```
332
340
 
333
341
  [⬆️ &nbsp;Back to Top](#table-of-contents-)
334
342
 
335
- ### List of all type checkers
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
  [⬆️ &nbsp;Back to Top](#table-of-contents-)
373
381
 
374
- ### Creating type checkers
382
+ ### Creating type handlers
375
383
 
376
- There are two ways to do this, you can create type checkers dynamically or defining a module.
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 checker can return its kind and its name
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 checker can return its kind and its name
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
  [⬆️ &nbsp;Back to Top](#table-of-contents-)
522
530
 
523
- #### Kind::<Type> module
531
+ #### Kind::<Type> object
524
532
 
525
- The idea here is to create a type checker inside of the `Kind` namespace, so to do this, you will only need to use pure Ruby. e.g:
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, TypeChecker
541
+ extend self, ::Kind::Object
534
542
 
535
- # Define the expected kind of this type checker.
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 checker (like: `Kind::Symbol`).
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 checker 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.
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
  [⬆️ &nbsp;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, < 6.1.0`](https://api.rubyonrails.org/classes/ActiveModel/Validations.html). e.g
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/active_model/validation'
1481
+ gem 'kind', require: 'kind/validator'
1474
1482
 
1475
1483
  # In some .rb file
1476
- require 'kind/active_model/validation'
1484
+ require 'kind/validator'
1477
1485
  ```
1478
1486
 
1479
1487
  [⬆️ &nbsp;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 checkers as the expected kinds.
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 simple type system (at runtime) for Ruby.}
10
- spec.description = %q{A simple type system (at runtime) for Ruby - free of dependencies.}
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.2.0')
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 'set'
4
- require 'ostruct'
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