kind 4.1.0 → 5.4.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 +39 -7
- data/.travis.yml +1 -2
- data/CHANGELOG.md +524 -29
- data/Gemfile +13 -6
- data/README.md +57 -43
- data/kind.gemspec +3 -3
- data/lib/kind.rb +2 -84
- 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 -2
- data/lib/kind/empty/constant.rb +7 -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 +84 -51
- data/lib/kind/active_model/kind_validator.rb +0 -103
- data/lib/kind/core.rb +0 -10
- data/lib/kind/core/deprecation.rb +0 -29
- data/lib/kind/core/kind.rb +0 -61
- data/lib/kind/core/undefined.rb +0 -7
- data/lib/kind/core/wrong_number_of_args.rb +0 -9
- data/lib/kind/deprecations/built_in_type_checkers.rb +0 -23
- data/lib/kind/deprecations/checker.rb +0 -16
- data/lib/kind/deprecations/checker/factory.rb +0 -31
- data/lib/kind/deprecations/checker/protocol.rb +0 -73
- data/lib/kind/deprecations/is.rb +0 -35
- data/lib/kind/deprecations/of.rb +0 -258
- data/lib/kind/deprecations/types.rb +0 -121
- 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
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'kind/basic'
|
4
|
+
|
5
|
+
module Kind
|
6
|
+
module Function
|
7
|
+
module Behavior
|
8
|
+
def self.extended(base)
|
9
|
+
base.send(:alias_method, :[], :call)
|
10
|
+
base.send(:alias_method, :===, :call)
|
11
|
+
base.send(:alias_method, :yield, :call)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.included(_)
|
16
|
+
raise RuntimeError, "The Kind::Function can't be included, it can be only extended."
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.extended(base)
|
20
|
+
base.extend(Kind.of_module(base))
|
21
|
+
end
|
22
|
+
|
23
|
+
def kind_function!
|
24
|
+
return self if Kind.is?(Behavior, self)
|
25
|
+
|
26
|
+
KIND.respond_to!(:call, self).extend(Behavior)
|
27
|
+
|
28
|
+
if method(:call).parameters.empty?
|
29
|
+
raise ArgumentError, "#{self.name}.call must receive at least one argument"
|
30
|
+
end
|
31
|
+
|
32
|
+
self.instance_eval(
|
33
|
+
'def to_proc; @to_proc ||= method(:call).to_proc; end' \
|
34
|
+
"\n" \
|
35
|
+
'def curry; @curry ||= to_proc.curry; end'
|
36
|
+
)
|
37
|
+
|
38
|
+
self.to_proc
|
39
|
+
self.curry
|
40
|
+
self
|
41
|
+
end
|
42
|
+
|
43
|
+
private_constant :Behavior
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'kind/basic'
|
4
|
+
require 'kind/empty'
|
5
|
+
require 'kind/__lib__/attributes'
|
6
|
+
|
7
|
+
module Kind
|
8
|
+
module Functional
|
9
|
+
def self.extended(_)
|
10
|
+
raise RuntimeError, "The Kind::Functional can't be extended, it can be only included."
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.included(base)
|
14
|
+
Kind.of_class(base).send(:extend, ClassMethods)
|
15
|
+
end
|
16
|
+
|
17
|
+
module Behavior
|
18
|
+
def self.included(base)
|
19
|
+
base.send(:alias_method, :[], :call)
|
20
|
+
base.send(:alias_method, :===, :call)
|
21
|
+
base.send(:alias_method, :yield, :call)
|
22
|
+
end
|
23
|
+
|
24
|
+
def initialize(arg = Empty::HASH)
|
25
|
+
hash = STRICT.kind_of(::Hash, arg)
|
26
|
+
|
27
|
+
self.class.__dependencies__.each do |name, (kind, default, _visibility)|
|
28
|
+
value_to_assign = ATTRIBUTES.value_to_assign!(kind, default, hash, name)
|
29
|
+
|
30
|
+
instance_variable_set("@#{name}", value_to_assign)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
module DependencyInjection
|
36
|
+
def __dependencies__ # :nodoc:
|
37
|
+
@__dependencies__ ||= {}
|
38
|
+
end
|
39
|
+
|
40
|
+
def dependency(name, kind, default: UNDEFINED)
|
41
|
+
__dependencies__[ATTRIBUTES.name!(name)] = ATTRIBUTES.value!(kind, default)
|
42
|
+
|
43
|
+
attr_reader(name)
|
44
|
+
|
45
|
+
private(name)
|
46
|
+
|
47
|
+
name
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
module ClassMethods
|
52
|
+
include DependencyInjection
|
53
|
+
|
54
|
+
def kind_functional!
|
55
|
+
return self if Kind.is?(Behavior, self)
|
56
|
+
|
57
|
+
public_methods = self.public_instance_methods - ::Object.new.methods
|
58
|
+
|
59
|
+
unless public_methods.include?(:call)
|
60
|
+
raise Kind::Error.new("expected #{self} to implement `#call`")
|
61
|
+
end
|
62
|
+
|
63
|
+
if public_methods.size > 1
|
64
|
+
raise Kind::Error.new("#{self} can only have `#call` as its public method")
|
65
|
+
end
|
66
|
+
|
67
|
+
if public_instance_method(:call).parameters.empty?
|
68
|
+
raise ArgumentError, "#{self.name}#call must receive at least one argument"
|
69
|
+
end
|
70
|
+
|
71
|
+
self.send(:include, Behavior)
|
72
|
+
|
73
|
+
def self.inherited(_)
|
74
|
+
raise RuntimeError, "#{self.name} is a Kind::Functional and it can't be inherited by anyone"
|
75
|
+
end
|
76
|
+
|
77
|
+
self.class_eval(
|
78
|
+
'def to_proc; @to_proc ||= method(:call).to_proc; end' \
|
79
|
+
"\n" \
|
80
|
+
'def curry; @curry ||= to_proc.curry; end'
|
81
|
+
)
|
82
|
+
|
83
|
+
__dependencies__.freeze
|
84
|
+
|
85
|
+
self
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'kind/functional'
|
4
|
+
require 'kind/functional/steps'
|
5
|
+
|
6
|
+
module Kind
|
7
|
+
module Functional::Action
|
8
|
+
CALL_TMPL = [
|
9
|
+
'def call(%s)',
|
10
|
+
' result = call!(%s)',
|
11
|
+
'',
|
12
|
+
' return result if Kind::Result::Monad === result',
|
13
|
+
'',
|
14
|
+
' raise Kind::Error, "#{self.class.name}#call! must return a Kind::Success or Kind::Failure"',
|
15
|
+
'end'
|
16
|
+
].join("\n").freeze
|
17
|
+
|
18
|
+
module Macros
|
19
|
+
def kind_functional_action!
|
20
|
+
return self if Kind.is?(Result::Methods, self)
|
21
|
+
|
22
|
+
public_methods = self.public_instance_methods - ::Object.new.methods
|
23
|
+
|
24
|
+
unless public_methods.include?(:call!)
|
25
|
+
raise Kind::Error.new("expected #{self} to implement `#call!`")
|
26
|
+
end
|
27
|
+
|
28
|
+
if public_methods.size > 1
|
29
|
+
raise Kind::Error.new("#{self} can only have `#call!` as its public method")
|
30
|
+
end
|
31
|
+
|
32
|
+
call_parameters = public_instance_method(:call!).parameters
|
33
|
+
|
34
|
+
if call_parameters.empty?
|
35
|
+
raise ArgumentError, "#{self.name}#call! must receive at least one argument"
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.inherited(_)
|
39
|
+
raise RuntimeError, "#{self.name} is a Kind::Functional::Action and it can't be inherited"
|
40
|
+
end
|
41
|
+
|
42
|
+
call_parameters.flatten!
|
43
|
+
|
44
|
+
call_with_args = call_parameters.include?(:req) || call_parameters.include?(:rest)
|
45
|
+
call_with_kargs = call_parameters.include?(:keyreq) || call_parameters.include?(:keyrest)
|
46
|
+
|
47
|
+
call_tmpl_args = '*args, **kargs' if call_with_args && call_with_kargs
|
48
|
+
call_tmpl_args = '*args' if call_with_args && !call_with_kargs
|
49
|
+
call_tmpl_args = '**kargs' if !call_with_args && call_with_kargs
|
50
|
+
|
51
|
+
self.class_eval(
|
52
|
+
"def to_proc; @to_proc ||= method(:call!).to_proc; end" \
|
53
|
+
"\n" \
|
54
|
+
"def curry; @curry ||= to_proc.curry; end" \
|
55
|
+
"\n" \
|
56
|
+
"#{CALL_TMPL % [call_tmpl_args, call_tmpl_args]}"
|
57
|
+
)
|
58
|
+
|
59
|
+
if Kind.of_module?(self)
|
60
|
+
self.send(:extend, Functional::Steps)
|
61
|
+
else
|
62
|
+
self.send(:include, Functional::Steps)
|
63
|
+
self.send(:include, Functional::Behavior)
|
64
|
+
|
65
|
+
__dependencies__.freeze
|
66
|
+
end
|
67
|
+
|
68
|
+
self.send(:protected, :call!)
|
69
|
+
|
70
|
+
self
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def self.included(base)
|
75
|
+
Kind.of_class(base).send(:extend, Functional::DependencyInjection)
|
76
|
+
|
77
|
+
base.send(:extend, Macros)
|
78
|
+
end
|
79
|
+
|
80
|
+
def self.extended(base)
|
81
|
+
base.send(:extend, Kind.of_module(base))
|
82
|
+
base.send(:extend, Macros)
|
83
|
+
end
|
84
|
+
|
85
|
+
private_constant :Macros, :CALL_TMPL
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'kind/basic'
|
4
|
+
require 'kind/empty'
|
5
|
+
require 'kind/result'
|
6
|
+
require 'kind/__lib__/action_steps'
|
7
|
+
|
8
|
+
module Kind
|
9
|
+
module Functional
|
10
|
+
module Steps
|
11
|
+
def self.extended(base)
|
12
|
+
base.extend(Result::Methods)
|
13
|
+
base.extend(ACTION_STEPS)
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.included(base)
|
17
|
+
base.send(:include, Result::Methods)
|
18
|
+
base.send(:include, ACTION_STEPS)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'kind/basic'
|
4
|
+
require 'kind/__lib__/attributes'
|
5
|
+
|
6
|
+
module Kind
|
7
|
+
module ImmutableAttributes
|
8
|
+
require 'kind/immutable_attributes/initializer'
|
9
|
+
require 'kind/immutable_attributes/reader'
|
10
|
+
|
11
|
+
module ClassMethods
|
12
|
+
def __attributes__ # :nodoc:
|
13
|
+
@__attributes__ ||= {}
|
14
|
+
end
|
15
|
+
|
16
|
+
def attribute(name, kind = nil, default: UNDEFINED, visibility: :public)
|
17
|
+
__attributes__[ATTRIBUTES.name!(name)] = ATTRIBUTES.value(kind, default, visibility)
|
18
|
+
|
19
|
+
attr_reader(name)
|
20
|
+
|
21
|
+
private(name) if visibility == :private
|
22
|
+
protected(name) if visibility == :protected
|
23
|
+
|
24
|
+
name
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.included(base)
|
29
|
+
base.extend(ClassMethods)
|
30
|
+
base.send(:include, Reader)
|
31
|
+
base.send(:include, Initializer)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'kind/__lib__/attributes'
|
4
|
+
require 'kind/basic'
|
5
|
+
require 'kind/empty'
|
6
|
+
|
7
|
+
module Kind
|
8
|
+
module ImmutableAttributes
|
9
|
+
module Initializer
|
10
|
+
def initialize(arg)
|
11
|
+
input = __resolve_attribute_input(arg)
|
12
|
+
|
13
|
+
hash = call_before_initialize_to_prepare_the_input(input)
|
14
|
+
|
15
|
+
@_nil_attrs = ::Set.new
|
16
|
+
@_____attrs = {}
|
17
|
+
@attributes = {}
|
18
|
+
|
19
|
+
self.class.__attributes__.each do |name, (kind, default, visibility)|
|
20
|
+
value_to_assign = __resolve_attribute_value_to_assign(kind, default, hash, name)
|
21
|
+
|
22
|
+
@_nil_attrs << name if value_to_assign.nil?
|
23
|
+
@_____attrs[name] = value_to_assign
|
24
|
+
@attributes[name] = value_to_assign if visibility == :public
|
25
|
+
|
26
|
+
instance_variable_set("@#{name}", value_to_assign)
|
27
|
+
end
|
28
|
+
|
29
|
+
@_nil_attrs.freeze
|
30
|
+
@attributes.freeze
|
31
|
+
|
32
|
+
call_after_initialize_and_assign_the_attributes
|
33
|
+
end
|
34
|
+
|
35
|
+
def nil_attributes
|
36
|
+
@_nil_attrs.to_a
|
37
|
+
end
|
38
|
+
|
39
|
+
def nil_attributes?(*names)
|
40
|
+
names.empty? ? !@_nil_attrs.empty? : names.all? { |name| @_nil_attrs.include?(name) }
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def call_before_initialize_to_prepare_the_input(input)
|
46
|
+
input
|
47
|
+
end
|
48
|
+
|
49
|
+
def call_after_initialize_and_assign_the_attributes
|
50
|
+
end
|
51
|
+
|
52
|
+
def __resolve_attribute_input(arg)
|
53
|
+
return arg.attributes if arg.kind_of?(ImmutableAttributes)
|
54
|
+
|
55
|
+
arg.kind_of?(::Hash) ? arg : Empty::HASH
|
56
|
+
end
|
57
|
+
|
58
|
+
def __resolve_attribute_value_to_assign(kind, default, hash, name)
|
59
|
+
if kind.kind_of?(::Class) && kind < ImmutableAttributes
|
60
|
+
kind.new(hash[name])
|
61
|
+
elsif kind.kind_of?(::Array) && (nkind = kind[0]).kind_of?(::Class) && nkind < ImmutableAttributes
|
62
|
+
Array(hash[name]).map { |item| nkind.new(item) }
|
63
|
+
else
|
64
|
+
ATTRIBUTES.value_to_assign(kind, default, hash, name)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'kind/basic'
|
4
|
+
require 'kind/__lib__/attributes'
|
5
|
+
|
6
|
+
module Kind
|
7
|
+
module ImmutableAttributes
|
8
|
+
|
9
|
+
module Reader
|
10
|
+
def self.included(base)
|
11
|
+
base.send(:attr_reader, :attributes)
|
12
|
+
end
|
13
|
+
|
14
|
+
def attribute?(name)
|
15
|
+
self.class.__attributes__.key?(name.to_sym)
|
16
|
+
end
|
17
|
+
|
18
|
+
def attribute(name)
|
19
|
+
@attributes[name.to_sym]
|
20
|
+
end
|
21
|
+
|
22
|
+
def attribute!(name)
|
23
|
+
@attributes.fetch(name.to_sym)
|
24
|
+
end
|
25
|
+
|
26
|
+
def with_attribute(name, value)
|
27
|
+
self.class.new(@_____attrs.merge(name.to_sym => value))
|
28
|
+
end
|
29
|
+
|
30
|
+
def with_attributes(arg)
|
31
|
+
hash = STRICT.kind_of(::Hash, arg)
|
32
|
+
|
33
|
+
self.class.new(@_____attrs.merge(hash))
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
data/lib/kind/maybe.rb
CHANGED
@@ -1,44 +1,69 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'kind/
|
3
|
+
require 'kind/basic'
|
4
4
|
|
5
5
|
module Kind
|
6
6
|
module Maybe
|
7
|
-
|
8
|
-
|
9
|
-
require 'kind/maybe/result'
|
7
|
+
require 'kind/maybe/monad'
|
10
8
|
require 'kind/maybe/none'
|
11
9
|
require 'kind/maybe/some'
|
12
|
-
require 'kind/maybe/
|
10
|
+
require 'kind/maybe/wrapper'
|
13
11
|
require 'kind/maybe/typed'
|
12
|
+
require 'kind/maybe/methods'
|
13
|
+
|
14
|
+
extend self
|
14
15
|
|
15
16
|
def new(value)
|
16
|
-
(KIND.
|
17
|
+
(::Exception === value || KIND.nil_or_undefined?(value) ? None : Some)
|
17
18
|
.new(value)
|
18
19
|
end
|
19
20
|
|
20
21
|
alias_method :[], :new
|
21
22
|
|
22
|
-
|
23
|
+
module Buildable
|
24
|
+
def maybe(value = UNDEFINED, &block)
|
25
|
+
return __maybe[value] if UNDEFINED != value && !block
|
26
|
+
return __maybe.wrap(&block) if UNDEFINED == value && block
|
27
|
+
return __maybe.wrap(value, &block) if UNDEFINED != value && block
|
28
|
+
|
29
|
+
__maybe
|
30
|
+
end
|
31
|
+
|
32
|
+
alias_method :optional, :maybe
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def __maybe
|
37
|
+
@__maybe ||= Maybe::Typed[self]
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
extend Wrapper
|
23
42
|
end
|
24
43
|
|
25
44
|
Optional = Maybe
|
26
45
|
|
27
|
-
None = Maybe
|
46
|
+
None = Maybe::NONE_INSTANCE
|
28
47
|
|
29
48
|
def self.None
|
30
|
-
|
49
|
+
Maybe::NONE_INSTANCE
|
31
50
|
end
|
32
51
|
|
33
52
|
def self.Some(value)
|
34
|
-
Maybe
|
53
|
+
Maybe::Some[value]
|
35
54
|
end
|
36
55
|
|
37
56
|
def self.Maybe(kind)
|
38
|
-
Maybe::Typed.
|
57
|
+
warn '[DEPRECATION] Kind::Maybe() is deprecated; use Kind::Maybe::Typed[] instead. ' \
|
58
|
+
'It will be removed on next major release.'
|
59
|
+
|
60
|
+
Maybe::Typed[kind]
|
39
61
|
end
|
40
62
|
|
41
63
|
def self.Optional(kind)
|
42
|
-
|
64
|
+
warn '[DEPRECATION] Kind::Optional() is deprecated; use Kind::Optional::Typed[] instead. ' \
|
65
|
+
'It will be removed on next major release.'
|
66
|
+
|
67
|
+
Optional::Typed[kind]
|
43
68
|
end
|
44
69
|
end
|