kind 1.9.0 → 3.0.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.
@@ -0,0 +1,73 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kind
4
+ class Checker
5
+ module Protocol
6
+ def class?(value)
7
+ Kind::Is.__call__(__kind, value)
8
+ end
9
+
10
+ def instance(value, options = Empty::HASH)
11
+ default = options[:or]
12
+
13
+ return Kind::Of.(__kind, value) if ::Kind::Maybe::Value.none?(default)
14
+
15
+ Kind::Undefined != value && instance?(value) ? value : Kind::Of.(__kind, default)
16
+ end
17
+
18
+ def [](value, options = options = Empty::HASH)
19
+ instance(value, options)
20
+ end
21
+
22
+ def to_proc
23
+ @to_proc ||=
24
+ -> checker { -> value { checker.instance(value) } }.call(self)
25
+ end
26
+
27
+ def __is_instance__(value)
28
+ value.kind_of?(__kind)
29
+ end
30
+
31
+ def is_instance_to_proc
32
+ @is_instance_to_proc ||=
33
+ -> checker { -> value { checker.__is_instance__(value) } }.call(self)
34
+ end
35
+
36
+ def instance?(*args)
37
+ return is_instance_to_proc if args.empty?
38
+
39
+ return args.all? { |object| __is_instance__(object) } if args.size > 1
40
+
41
+ arg = args[0]
42
+ Kind::Undefined == arg ? is_instance_to_proc : __is_instance__(arg)
43
+ end
44
+
45
+ def or_nil(value)
46
+ return value if instance?(value)
47
+ end
48
+
49
+ def or_undefined(value)
50
+ or_nil(value) || Kind::Undefined
51
+ end
52
+
53
+ def __as_maybe__(value)
54
+ Kind::Maybe.new(or_nil(value))
55
+ end
56
+
57
+ def as_maybe_to_proc
58
+ @as_maybe_to_proc ||=
59
+ -> checker { -> value { checker.__as_maybe__(value) } }.call(self)
60
+ end
61
+
62
+ def as_maybe(value = Kind::Undefined)
63
+ return __as_maybe__(value) if Kind::Undefined != value
64
+
65
+ as_maybe_to_proc
66
+ end
67
+
68
+ def as_optional(value = Kind::Undefined)
69
+ as_maybe(value)
70
+ end
71
+ end
72
+ end
73
+ end
@@ -7,7 +7,7 @@ module Kind
7
7
  private_constant :UNDEFINED_OBJECT
8
8
 
9
9
  def initialize(arg, object = UNDEFINED_OBJECT)
10
- if object == UNDEFINED_OBJECT
10
+ if UNDEFINED_OBJECT == object
11
11
  # Will be used when the exception was raised with a message. e.g:
12
12
  # raise Kind::Error, "some message"
13
13
  super(arg)
@@ -2,9 +2,22 @@
2
2
 
3
3
  module Kind
4
4
  module Maybe
5
+ class Typed
6
+ def initialize(kind)
7
+ @kind_checker = Kind::Checker::Factory.create(kind)
8
+ end
9
+
10
+ def wrap(value)
11
+ @kind_checker.as_maybe(value)
12
+ end
13
+
14
+ alias_method :new, :wrap
15
+ alias_method :[], :wrap
16
+ end
17
+
5
18
  module Value
6
19
  def self.none?(value)
7
- value == nil || value == Undefined
20
+ value.nil? || Undefined == value
8
21
  end
9
22
 
10
23
  def self.some?(value)
@@ -16,7 +29,7 @@ module Kind
16
29
  attr_reader :value
17
30
 
18
31
  def initialize(value)
19
- @value = value
32
+ @value = value.kind_of?(Result) ? value.value : value
20
33
  end
21
34
 
22
35
  def value_or(method_name = Undefined, &block)
@@ -42,9 +55,9 @@ module Kind
42
55
  INVALID_DEFAULT_ARG = 'the default value must be defined as an argument or block'.freeze
43
56
 
44
57
  def value_or(default = Undefined, &block)
45
- raise ArgumentError, INVALID_DEFAULT_ARG if default == Undefined && !block
58
+ raise ArgumentError, INVALID_DEFAULT_ARG if Undefined == default && !block
46
59
 
47
- Maybe::Value.some?(default) ? default : block.call
60
+ Undefined != default ? default : block.call
48
61
  end
49
62
 
50
63
  def none?; true; end
@@ -55,12 +68,14 @@ module Kind
55
68
 
56
69
  alias_method :then, :map
57
70
 
58
- def try(method_name = Undefined, &block)
59
- Kind.of.Symbol(method_name) if method_name != Undefined
71
+ def try!(method_name = Undefined, &block)
72
+ Kind.of.Symbol(method_name) if Undefined != method_name
60
73
 
61
- nil
74
+ NONE_WITH_NIL_VALUE
62
75
  end
63
76
 
77
+ alias_method :try, :try!
78
+
64
79
  private_constant :INVALID_DEFAULT_ARG
65
80
  end
66
81
 
@@ -79,32 +94,90 @@ module Kind
79
94
  def map(&fn)
80
95
  result = fn.call(@value)
81
96
 
82
- return NONE_WITH_NIL_VALUE if result == nil
83
- return NONE_WITH_UNDEFINED_VALUE if result == Undefined
84
-
85
- Some.new(result)
97
+ resolve(result)
86
98
  end
87
99
 
88
100
  alias_method :then, :map
89
101
 
90
- def try(method_name = Undefined, *args, &block)
91
- fn = method_name == Undefined ? block : Kind.of.Symbol(method_name).to_proc
102
+ def try!(method_name = Undefined, *args, &block)
103
+ Kind::Of::Symbol(method_name) if Undefined != method_name
92
104
 
93
- result = args.empty? ? fn.call(value) : fn.call(*args.unshift(value))
105
+ __try__(method_name, args, block)
106
+ end
94
107
 
95
- return result if Maybe::Value.some?(result)
108
+ def try(method_name = Undefined, *args, &block)
109
+ if (Undefined != method_name && value.respond_to?(Kind::Of::Symbol(method_name))) ||
110
+ (Undefined == method_name && block)
111
+ __try__(method_name, args, block)
112
+ else
113
+ NONE_WITH_NIL_VALUE
114
+ end
96
115
  end
116
+
117
+ private
118
+
119
+ def __try__(method_name = Undefined, args, block)
120
+ fn = Undefined == method_name ? block : method_name.to_proc
121
+
122
+ result = args.empty? ? fn.call(value) : fn.call(*args.unshift(value))
123
+
124
+ resolve(result)
125
+ end
126
+
127
+ def resolve(result)
128
+ return result if Maybe::None === result
129
+ return NONE_WITH_NIL_VALUE if result.nil?
130
+ return NONE_WITH_UNDEFINED_VALUE if Undefined == result
131
+
132
+ Some.new(result)
133
+ end
97
134
  end
98
135
 
99
136
  def self.new(value)
100
137
  result_type = Maybe::Value.none?(value) ? None : Some
101
- result_type.new(value.is_a?(Result) ? value.value : value)
138
+ result_type.new(value)
102
139
  end
103
140
 
104
- def self.[](value);
141
+ def self.[](value)
105
142
  new(value)
106
143
  end
144
+
145
+ def self.wrap(value)
146
+ new(value)
147
+ end
148
+
149
+ def self.none
150
+ NONE_WITH_NIL_VALUE
151
+ end
152
+
153
+ VALUE_CANT_BE_NONE = "value can't be nil or Kind::Undefined".freeze
154
+
155
+ private_constant :VALUE_CANT_BE_NONE
156
+
157
+ def self.some(value)
158
+ return Maybe::Some.new(value) if Value.some?(value)
159
+
160
+ raise ArgumentError, VALUE_CANT_BE_NONE
161
+ end
107
162
  end
108
163
 
109
164
  Optional = Maybe
165
+
166
+ None = Maybe.none
167
+
168
+ def self.None
169
+ Kind::None
170
+ end
171
+
172
+ def self.Some(value)
173
+ Maybe.some(value)
174
+ end
175
+
176
+ def self.Maybe(kind)
177
+ Maybe::Typed.new(kind)
178
+ end
179
+
180
+ def self.Optional(kind)
181
+ Maybe::Typed.new(kind)
182
+ end
110
183
  end
@@ -10,15 +10,25 @@ module Kind
10
10
  def self.%{method_name}(object = Undefined, options = Empty::HASH)
11
11
  default = options[:or]
12
12
 
13
- return Kind::Of::%{kind_name} if object == Undefined && default.nil?
13
+ return Kind::Of::%{kind_name} if Undefined == object && default.nil?
14
14
 
15
- Kind::Of.(::%{kind_name_to_check}, (object || default))
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
 
19
29
  KIND_IS = <<-RUBY
20
30
  def self.%{method_name}(value = Undefined)
21
- return Kind::Is::%{kind_name} if value == Undefined
31
+ return Kind::Is::%{kind_name} if Undefined == value
22
32
 
23
33
  Kind::Is.__call__(::%{kind_name_to_check}, value)
24
34
  end
@@ -88,11 +98,12 @@ module Kind
88
98
  kind_name = params[:kind_name]
89
99
  params[:kind_name_to_check] ||= kind_name
90
100
 
91
- kind_checker = ::Module.new { extend Checkable }
101
+ kind_checker = ::Module.new { extend Checker::Protocol }
92
102
  kind_checker.module_eval("def self.__kind; #{params[:kind_name_to_check]}; end")
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)
@@ -19,7 +19,7 @@ module Kind
19
19
  end
20
20
 
21
21
  def undefined.default(value, default)
22
- return self if value != self
22
+ return self if self != value
23
23
 
24
24
  default.respond_to?(:call) ? default.call : default
25
25
  end
@@ -2,10 +2,10 @@
2
2
 
3
3
  module Kind
4
4
  module Validator
5
- DEFAULT_STRATEGIES = Set.new(%w[instance_of kind_of is_a]).freeze
5
+ DEFAULT_STRATEGIES = Set.new(%w[instance_of kind_of]).freeze
6
6
 
7
7
  class InvalidDefinition < ArgumentError
8
- OPTIONS = 'Options to define one: :of, :instance_of, :respond_to, :klass, :array_of or :array_with'.freeze
8
+ OPTIONS = 'Options to define one: :of, :is, :respond_to, :instance_of, :array_of or :array_with'.freeze
9
9
 
10
10
  def initialize(attribute)
11
11
  super "invalid type definition for :#{attribute} attribute. #{OPTIONS}"
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Kind
4
- VERSION = '1.9.0'
4
+ VERSION = '3.0.0'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kind
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.9.0
4
+ version: 3.0.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-06 00:00:00.000000000 Z
11
+ date: 2020-06-25 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: A simple type system (at runtime) for Ruby - free of dependencies.
14
14
  email:
@@ -32,6 +32,8 @@ files:
32
32
  - lib/kind/active_model/kind_validator.rb
33
33
  - lib/kind/active_model/validation.rb
34
34
  - lib/kind/checker.rb
35
+ - lib/kind/checker/factory.rb
36
+ - lib/kind/checker/protocol.rb
35
37
  - lib/kind/empty.rb
36
38
  - lib/kind/error.rb
37
39
  - lib/kind/is.rb