kind 1.9.0 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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