fear 0.11.0 → 1.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.
- checksums.yaml +5 -5
- data/.gitignore +0 -1
- data/.rubocop.yml +18 -0
- data/.travis.yml +0 -3
- data/CHANGELOG.md +12 -1
- data/Gemfile +1 -0
- data/{gemfiles/dry_equalizer_0.2.1.gemfile.lock → Gemfile.lock} +21 -12
- data/README.md +594 -241
- data/Rakefile +166 -219
- data/benchmarks/README.md +1 -0
- data/benchmarks/dry_do_vs_fear_for.txt +11 -0
- data/benchmarks/dry_some_fmap_vs_fear_some_map.txt +11 -0
- data/benchmarks/factorial.txt +16 -0
- data/benchmarks/fear_gaurd_and1_vs_new.txt +13 -0
- data/benchmarks/fear_gaurd_and2_vs_and.txt +13 -0
- data/benchmarks/fear_gaurd_and3_vs_and_and.txt +13 -0
- data/benchmarks/fear_pattern_extracting_with_vs_without_cache.txt +11 -0
- data/benchmarks/fear_pattern_matching_construction_vs_execution.txt +13 -0
- data/benchmarks/pattern_matching_dry_vs_qo_vs_fear_try.txt +14 -0
- data/benchmarks/pattern_matching_qo_vs_fear_pattern_extraction.txt +11 -0
- data/benchmarks/pattern_matching_qo_vs_fear_try_execution.txt +11 -0
- data/examples/pattern_extracting.rb +15 -0
- data/examples/pattern_matching_binary_tree_set.rb +96 -0
- data/examples/pattern_matching_number_in_words.rb +54 -0
- data/fear.gemspec +4 -2
- data/lib/fear.rb +21 -4
- data/lib/fear/either.rb +77 -59
- data/lib/fear/either_api.rb +21 -0
- data/lib/fear/empty_partial_function.rb +1 -1
- data/lib/fear/extractor.rb +108 -0
- data/lib/fear/extractor/anonymous_array_splat_matcher.rb +8 -0
- data/lib/fear/extractor/any_matcher.rb +15 -0
- data/lib/fear/extractor/array_head_matcher.rb +34 -0
- data/lib/fear/extractor/array_matcher.rb +38 -0
- data/lib/fear/extractor/array_splat_matcher.rb +14 -0
- data/lib/fear/extractor/empty_list_matcher.rb +18 -0
- data/lib/fear/extractor/extractor_matcher.rb +42 -0
- data/lib/fear/extractor/grammar.rb +201 -0
- data/lib/fear/extractor/grammar.treetop +129 -0
- data/lib/fear/extractor/identifier_matcher.rb +16 -0
- data/lib/fear/extractor/matcher.rb +54 -0
- data/lib/fear/extractor/matcher/and.rb +36 -0
- data/lib/fear/extractor/named_array_splat_matcher.rb +15 -0
- data/lib/fear/extractor/pattern.rb +55 -0
- data/lib/fear/extractor/typed_identifier_matcher.rb +24 -0
- data/lib/fear/extractor/value_matcher.rb +17 -0
- data/lib/fear/extractor_api.rb +33 -0
- data/lib/fear/failure.rb +32 -10
- data/lib/fear/for.rb +14 -69
- data/lib/fear/for_api.rb +66 -0
- data/lib/fear/future.rb +414 -0
- data/lib/fear/future_api.rb +19 -0
- data/lib/fear/left.rb +8 -0
- data/lib/fear/none.rb +17 -8
- data/lib/fear/option.rb +55 -49
- data/lib/fear/option_api.rb +38 -0
- data/lib/fear/partial_function.rb +9 -12
- data/lib/fear/partial_function/empty.rb +1 -1
- data/lib/fear/partial_function/guard.rb +8 -20
- data/lib/fear/partial_function/lifted.rb +1 -0
- data/lib/fear/partial_function_class.rb +10 -0
- data/lib/fear/pattern_match.rb +10 -0
- data/lib/fear/pattern_matching_api.rb +35 -11
- data/lib/fear/promise.rb +87 -0
- data/lib/fear/right.rb +8 -0
- data/lib/fear/some.rb +22 -3
- data/lib/fear/success.rb +22 -1
- data/lib/fear/try.rb +82 -67
- data/lib/fear/try_api.rb +31 -0
- data/lib/fear/unit.rb +28 -0
- data/lib/fear/version.rb +1 -1
- data/spec/fear/done_spec.rb +3 -3
- data/spec/fear/either/mixin_spec.rb +15 -0
- data/spec/fear/either_pattern_match_spec.rb +10 -12
- data/spec/fear/extractor/array_matcher_spec.rb +228 -0
- data/spec/fear/extractor/extractor_matcher_spec.rb +151 -0
- data/spec/fear/extractor/grammar_array_spec.rb +23 -0
- data/spec/fear/extractor/identified_matcher_spec.rb +47 -0
- data/spec/fear/extractor/identifier_matcher_spec.rb +66 -0
- data/spec/fear/extractor/pattern_spec.rb +32 -0
- data/spec/fear/extractor/typed_identifier_matcher_spec.rb +62 -0
- data/spec/fear/extractor/value_matcher_number_spec.rb +77 -0
- data/spec/fear/extractor/value_matcher_string_spec.rb +86 -0
- data/spec/fear/extractor/value_matcher_symbol_spec.rb +69 -0
- data/spec/fear/extractor_api_spec.rb +113 -0
- data/spec/fear/extractor_spec.rb +59 -0
- data/spec/fear/failure_spec.rb +73 -13
- data/spec/fear/for_spec.rb +35 -35
- data/spec/fear/future_spec.rb +466 -0
- data/spec/fear/guard_spec.rb +4 -4
- data/spec/fear/left_spec.rb +40 -14
- data/spec/fear/none_spec.rb +28 -12
- data/spec/fear/option/mixin_spec.rb +37 -0
- data/spec/fear/option_pattern_match_spec.rb +7 -9
- data/spec/fear/partial_function_spec.rb +25 -3
- data/spec/fear/pattern_match_spec.rb +33 -1
- data/spec/fear/promise_spec.rb +94 -0
- data/spec/fear/right_spec.rb +37 -9
- data/spec/fear/some_spec.rb +32 -6
- data/spec/fear/success_spec.rb +32 -4
- data/spec/fear/try/mixin_spec.rb +17 -0
- data/spec/fear/try_pattern_match_spec.rb +8 -10
- data/spec/spec_helper.rb +1 -1
- metadata +115 -20
- data/Appraisals +0 -32
- data/gemfiles/dry_equalizer_0.1.0.gemfile +0 -8
- data/gemfiles/dry_equalizer_0.1.0.gemfile.lock +0 -82
- data/gemfiles/dry_equalizer_0.2.1.gemfile +0 -8
- data/lib/fear/done.rb +0 -22
- data/spec/fear/option_spec.rb +0 -15
@@ -3,6 +3,16 @@ module Fear
|
|
3
3
|
class PartialFunctionClass
|
4
4
|
include PartialFunction
|
5
5
|
|
6
|
+
# @param condition [#call] describes the domain of partial function
|
7
|
+
# @param function [Proc] function definition
|
8
|
+
def initialize(condition, &function)
|
9
|
+
@condition = condition
|
10
|
+
@function = function
|
11
|
+
end
|
12
|
+
attr_reader :condition, :function
|
13
|
+
private :condition
|
14
|
+
private :function
|
15
|
+
|
6
16
|
# @param arg [any]
|
7
17
|
# @return [any] Calls this partial function with the given argument when it
|
8
18
|
# is contained in the function domain.
|
data/lib/fear/pattern_match.rb
CHANGED
@@ -93,6 +93,16 @@ module Fear
|
|
93
93
|
or_else(Fear.case(*guards, &effect))
|
94
94
|
end
|
95
95
|
|
96
|
+
# @param pattern [String]
|
97
|
+
# @param guards [<#===>]
|
98
|
+
# @param effect [Proc]
|
99
|
+
# @return [Fear::PartialFunction]
|
100
|
+
# @see #case for details
|
101
|
+
# @see Fear.xcase for details
|
102
|
+
def xcase(pattern, *guards, &effect)
|
103
|
+
or_else(Fear.xcase(pattern, *guards, &effect))
|
104
|
+
end
|
105
|
+
|
96
106
|
# @see Fear::PartialFunction#or_else
|
97
107
|
def or_else(other)
|
98
108
|
self.result = result.or_else(other)
|
@@ -34,16 +34,19 @@ module Fear
|
|
34
34
|
#
|
35
35
|
# m.case(20..40) { |m| "#{m} is within range" }
|
36
36
|
# m.case(->(x) { x > 10}) { |m| "#{m} is greater than 10" }
|
37
|
+
# m.case(:even?.to_proc) { |x| "#{x} is even" }
|
38
|
+
# m.case(:odd?.to_proc) { |x| "#{x} is odd" }
|
37
39
|
#
|
38
|
-
#
|
40
|
+
# It's also possible to pass several guardians. All should match to pass
|
39
41
|
#
|
40
|
-
# m.case(:even
|
41
|
-
# m.case(:odd
|
42
|
+
# m.case(Integer, :even?.to_proc) { |x| ... }
|
43
|
+
# m.case(Integer, :odd?.to_proc) { |x| ... }
|
42
44
|
#
|
43
|
-
#
|
45
|
+
# If you want to perform pattern destruction, use +#xcase+ method
|
44
46
|
#
|
45
|
-
# m.
|
46
|
-
#
|
47
|
+
# m.xcase('Date(year, 12, 31)') { |year:| "Last day of the year #{year}" }
|
48
|
+
#
|
49
|
+
# The pattern above ensures that it's 31 of December and extracts year to block named parameter
|
47
50
|
#
|
48
51
|
# Since matcher returns +Fear::PartialFunction+, you can combine matchers using
|
49
52
|
# partial function API:
|
@@ -59,7 +62,7 @@ module Fear
|
|
59
62
|
#
|
60
63
|
# response = failures.or_else(success)
|
61
64
|
#
|
62
|
-
# @yieldparam matcher [Fear::
|
65
|
+
# @yieldparam matcher [Fear::PatternMatch]
|
63
66
|
# @return [Fear::PartialFunction]
|
64
67
|
# @see Fear::OptionPatternMatch for example of custom matcher
|
65
68
|
def matcher(&block)
|
@@ -70,8 +73,8 @@ module Fear
|
|
70
73
|
#
|
71
74
|
# @example
|
72
75
|
# Fear.match(42) do |m|
|
73
|
-
# m.case(Integer, :even
|
74
|
-
# m.case(Integer, :odd
|
76
|
+
# m.case(Integer, :even?.to_proc) { |n| "#{n} is even number" }
|
77
|
+
# m.case(Integer, :odd?.to_proc) { |n| "#{n} is odd number" }
|
75
78
|
# m.case(Strings) { |n| "#{n} is a string" }
|
76
79
|
# m.else { 'unknown' }
|
77
80
|
# end #=> "42 is even number"
|
@@ -91,7 +94,7 @@ module Fear
|
|
91
94
|
# pf.defined_at?('Foo') #=> false
|
92
95
|
#
|
93
96
|
# @example multiple guards combined using logical "and"
|
94
|
-
# pf = Fear.case(Integer, :even
|
97
|
+
# pf = Fear.case(Integer, :even?.to_proc) { |x| x / 2 }
|
95
98
|
# pf.defined_at?(4) #=> true
|
96
99
|
# pf.defined_at?(3) #=> false
|
97
100
|
#
|
@@ -100,11 +103,32 @@ module Fear
|
|
100
103
|
# @example
|
101
104
|
# Fear.case(Qo[age: 20..30]) { |_| 'old enough' }
|
102
105
|
#
|
103
|
-
# @param guards [
|
106
|
+
# @param guards [<#===>]
|
104
107
|
# @param function [Proc]
|
105
108
|
# @return [Fear::PartialFunction]
|
106
109
|
def case(*guards, &function)
|
107
110
|
PartialFunction.and(*guards, &function)
|
108
111
|
end
|
112
|
+
|
113
|
+
# Creates partial function defined on domain described with guard
|
114
|
+
# and perform pattern extraction.
|
115
|
+
#
|
116
|
+
# @param pattern [String] pattern to match against
|
117
|
+
# @param guards [<#===>] other guards against extracted pattern
|
118
|
+
# @yieldparam hash [{Symbol => any}]
|
119
|
+
# @return [Fear::PartialFunction]
|
120
|
+
#
|
121
|
+
# @example
|
122
|
+
# pf = Fear.xcase('['ok', Some(body)]') { |body:| ... }
|
123
|
+
# pf.defined_at?(['ok', Fear.some(body)]) #=> true
|
124
|
+
# pf.defined_at?(['err', Fear.none]) #=> false
|
125
|
+
#
|
126
|
+
# @example pattern and guards. It matches against non-empty body
|
127
|
+
#
|
128
|
+
# pf = Fear.xcase('['ok', Some(body)]', ->(body:) { !body.empty? }) { }
|
129
|
+
#
|
130
|
+
def xcase(pattern, *guards, &function)
|
131
|
+
Fear[pattern].and_then(self.case(*guards, &function))
|
132
|
+
end
|
109
133
|
end
|
110
134
|
end
|
data/lib/fear/promise.rb
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
module Fear
|
2
|
+
# @api private
|
3
|
+
class Promise < Concurrent::IVar
|
4
|
+
# @param options [Hash] options passed to underlying +Concurrent::Future+
|
5
|
+
def initialize(options = {})
|
6
|
+
super()
|
7
|
+
@options = options
|
8
|
+
@promise = Concurrent::Promise.new(options) do
|
9
|
+
Fear.try { value }.flatten
|
10
|
+
end
|
11
|
+
end
|
12
|
+
attr_reader :promise, :options
|
13
|
+
private :promise
|
14
|
+
private :options
|
15
|
+
|
16
|
+
def completed?
|
17
|
+
complete?
|
18
|
+
end
|
19
|
+
|
20
|
+
# @return [Fear::Future]
|
21
|
+
def to_future
|
22
|
+
Future.new(promise, options)
|
23
|
+
end
|
24
|
+
|
25
|
+
# Complete this promise with successful result
|
26
|
+
# @param value [any]
|
27
|
+
# @return [Boolean]
|
28
|
+
# @see #complete
|
29
|
+
def success(value)
|
30
|
+
complete(Fear.success(value))
|
31
|
+
end
|
32
|
+
|
33
|
+
# Complete this promise with failure
|
34
|
+
# @param value [any]
|
35
|
+
# @return [self]
|
36
|
+
# @raise [IllegalStateException]
|
37
|
+
# @see #complete!
|
38
|
+
def success!(value)
|
39
|
+
complete!(Fear.success(value))
|
40
|
+
end
|
41
|
+
|
42
|
+
# Complete this promise with failure
|
43
|
+
# @param error [StandardError]
|
44
|
+
# @return [Boolean]
|
45
|
+
# @see #complete
|
46
|
+
def failure(error)
|
47
|
+
complete(Fear.failure(error))
|
48
|
+
end
|
49
|
+
|
50
|
+
# Complete this promise with failure
|
51
|
+
# @param error [StandardError]
|
52
|
+
# @return [self]
|
53
|
+
# @raise [IllegalStateException]
|
54
|
+
# @see #complete!
|
55
|
+
def failure!(error)
|
56
|
+
complete!(Fear.failure(error))
|
57
|
+
end
|
58
|
+
|
59
|
+
# Complete this promise with result
|
60
|
+
# @param result [Fear::Try]
|
61
|
+
# @return [self]
|
62
|
+
# @raise [IllegalStateException] if promise already completed
|
63
|
+
def complete!(result)
|
64
|
+
if complete(result)
|
65
|
+
self
|
66
|
+
else
|
67
|
+
raise IllegalStateException, 'Promise already completed.'
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# Complete this promise with result
|
72
|
+
# @param result [Fear::Try]
|
73
|
+
# @return [Boolean] If the promise has already been completed returns
|
74
|
+
# `false`, or `true` otherwise.
|
75
|
+
# @raise [IllegalStateException] if promise already completed
|
76
|
+
#
|
77
|
+
def complete(result)
|
78
|
+
if completed?
|
79
|
+
false
|
80
|
+
else
|
81
|
+
set result
|
82
|
+
promise.execute
|
83
|
+
true
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
data/lib/fear/right.rb
CHANGED
data/lib/fear/some.rb
CHANGED
@@ -1,15 +1,20 @@
|
|
1
1
|
module Fear
|
2
2
|
class Some
|
3
3
|
include Option
|
4
|
-
include Dry::Equalizer(:get)
|
5
4
|
include RightBiased::Right
|
6
5
|
include SomePatternMatch.mixin
|
7
6
|
|
7
|
+
EXTRACTOR = proc do |option|
|
8
|
+
if Fear::Some === option
|
9
|
+
Fear.some([option.get])
|
10
|
+
else
|
11
|
+
Fear.none
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
8
15
|
attr_reader :value
|
9
16
|
protected :value
|
10
17
|
|
11
|
-
# FIXME: nice inspect
|
12
|
-
|
13
18
|
def initialize(value)
|
14
19
|
@value = value
|
15
20
|
end
|
@@ -46,5 +51,19 @@ module Fear
|
|
46
51
|
self
|
47
52
|
end
|
48
53
|
end
|
54
|
+
|
55
|
+
# @param other [Any]
|
56
|
+
# @return [Boolean]
|
57
|
+
def ==(other)
|
58
|
+
other.is_a?(Some) && get == other.get
|
59
|
+
end
|
60
|
+
|
61
|
+
# @return [String]
|
62
|
+
def inspect
|
63
|
+
"#<Fear::Some get=#{value.inspect}>"
|
64
|
+
end
|
65
|
+
|
66
|
+
# @return [String]
|
67
|
+
alias to_s inspect
|
49
68
|
end
|
50
69
|
end
|
data/lib/fear/success.rb
CHANGED
@@ -1,10 +1,17 @@
|
|
1
1
|
module Fear
|
2
2
|
class Success
|
3
3
|
include Try
|
4
|
-
include Dry::Equalizer(:value)
|
5
4
|
include RightBiased::Right
|
6
5
|
include SuccessPatternMatch.mixin
|
7
6
|
|
7
|
+
EXTRACTOR = proc do |try|
|
8
|
+
if Fear::Success === try
|
9
|
+
Fear.some([try.get])
|
10
|
+
else
|
11
|
+
Fear.none
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
8
15
|
attr_reader :value
|
9
16
|
protected :value
|
10
17
|
|
@@ -83,5 +90,19 @@ module Fear
|
|
83
90
|
def to_either
|
84
91
|
Right.new(value)
|
85
92
|
end
|
93
|
+
|
94
|
+
# @param other [Any]
|
95
|
+
# @return [Boolean]
|
96
|
+
def ==(other)
|
97
|
+
other.is_a?(Success) && value == other.value
|
98
|
+
end
|
99
|
+
|
100
|
+
# @return [String]
|
101
|
+
def inspect
|
102
|
+
"#<Fear::Success value=#{value.inspect}>"
|
103
|
+
end
|
104
|
+
|
105
|
+
# @return [String]
|
106
|
+
alias to_s inspect
|
86
107
|
end
|
87
108
|
end
|
data/lib/fear/try.rb
CHANGED
@@ -11,8 +11,8 @@ module Fear
|
|
11
11
|
# @example
|
12
12
|
# include Fear::Try::Mixin
|
13
13
|
#
|
14
|
-
# dividend =
|
15
|
-
# divisor =
|
14
|
+
# dividend = Fear.try { Integer(params[:dividend]) }
|
15
|
+
# divisor = Fear.try { Integer(params[:divisor]) }
|
16
16
|
# problem = dividend.flat_map { |x| divisor.map { |y| x / y } }
|
17
17
|
#
|
18
18
|
# problem.match |m|
|
@@ -53,13 +53,13 @@ module Fear
|
|
53
53
|
# @yieldreturn [any]
|
54
54
|
# @return [any]
|
55
55
|
# @example
|
56
|
-
#
|
57
|
-
#
|
56
|
+
# Fear.success(42).get_or_else { 24/2 } #=> 42
|
57
|
+
# Fear.failure(ArgumentError.new).get_or_else { 24/2 } #=> 12
|
58
58
|
# @overload get_or_else(default)
|
59
59
|
# @return [any]
|
60
60
|
# @example
|
61
|
-
#
|
62
|
-
#
|
61
|
+
# Fear.success(42).get_or_else(12) #=> 42
|
62
|
+
# Fear.failure(ArgumentError.new).get_or_else(12) #=> 12
|
63
63
|
#
|
64
64
|
# @!method include?(other_value)
|
65
65
|
# Returns +true+ if it has an element that is equal
|
@@ -67,9 +67,9 @@ module Fear
|
|
67
67
|
# @param [any]
|
68
68
|
# @return [Boolean]
|
69
69
|
# @example
|
70
|
-
#
|
71
|
-
#
|
72
|
-
#
|
70
|
+
# Fear.success(17).include?(17) #=> true
|
71
|
+
# Fear.success(17).include?(7) #=> false
|
72
|
+
# Fear.failure(ArgumentError.new).include?(17) #=> false
|
73
73
|
#
|
74
74
|
# @!method each(&block)
|
75
75
|
# Performs the given block if this is a +Success+.
|
@@ -78,11 +78,11 @@ module Fear
|
|
78
78
|
# @yieldreturn [void]
|
79
79
|
# @return [Try] itself
|
80
80
|
# @example
|
81
|
-
#
|
81
|
+
# Fear.success(17).each do |value|
|
82
82
|
# puts value
|
83
83
|
# end #=> prints 17
|
84
84
|
#
|
85
|
-
#
|
85
|
+
# Fear.failure(ArgumentError.new).each do |value|
|
86
86
|
# puts value
|
87
87
|
# end #=> does nothing
|
88
88
|
#
|
@@ -92,8 +92,8 @@ module Fear
|
|
92
92
|
# @yieldparam [any] value
|
93
93
|
# @yieldreturn [any]
|
94
94
|
# @example
|
95
|
-
#
|
96
|
-
#
|
95
|
+
# Fear.success(42).map { |v| v/2 } #=> Fear.success(21)
|
96
|
+
# Fear.failure(ArgumentError.new).map { |v| v/2 } #=> Fear.failure(ArgumentError.new)
|
97
97
|
#
|
98
98
|
# @!method flat_map(&block)
|
99
99
|
# Returns the given block applied to the value from this +Success+
|
@@ -102,18 +102,18 @@ module Fear
|
|
102
102
|
# @yieldreturn [Try]
|
103
103
|
# @return [Try]
|
104
104
|
# @example
|
105
|
-
#
|
106
|
-
# #=>
|
107
|
-
#
|
108
|
-
# #=>
|
105
|
+
# Fear.success(42).flat_map { |v| Fear.success(v/2) }
|
106
|
+
# #=> Fear.success(21)
|
107
|
+
# Fear.failure(ArgumentError.new).flat_map { |v| Fear.success(v/2) }
|
108
|
+
# #=> Fear.failure(ArgumentError.new)
|
109
109
|
#
|
110
110
|
# @!method to_option
|
111
111
|
# Returns an +Some+ containing the +Success+ value or a +None+ if
|
112
112
|
# this is a +Failure+.
|
113
113
|
# @return [Option]
|
114
114
|
# @example
|
115
|
-
#
|
116
|
-
#
|
115
|
+
# Fear.success(42).to_option #=> Fear.some(21)
|
116
|
+
# Fear.failure(ArgumentError.new).to_option #=> Fear.none()
|
117
117
|
#
|
118
118
|
# @!method any?(&predicate)
|
119
119
|
# Returns +false+ if +Failure+ or returns the result of the
|
@@ -122,9 +122,9 @@ module Fear
|
|
122
122
|
# @yieldreturn [Boolean]
|
123
123
|
# @return [Boolean]
|
124
124
|
# @example
|
125
|
-
#
|
126
|
-
#
|
127
|
-
#
|
125
|
+
# Fear.success(12).any?( |v| v > 10) #=> true
|
126
|
+
# Fear.success(7).any?( |v| v > 10) #=> false
|
127
|
+
# Fear.failure(ArgumentError.new).any?( |v| v > 10) #=> false
|
128
128
|
#
|
129
129
|
# ---
|
130
130
|
#
|
@@ -141,26 +141,27 @@ module Fear
|
|
141
141
|
# if this is a +Failure+.
|
142
142
|
# @return [any]
|
143
143
|
# @example
|
144
|
-
#
|
145
|
-
#
|
144
|
+
# Fear.success(42).get #=> 42
|
145
|
+
# Fear.failure(ArgumentError.new).get #=> ArgumentError: ArgumentError
|
146
146
|
#
|
147
147
|
# @!method or_else(&alternative)
|
148
148
|
# Returns this +Try+ if it's a +Success+ or the given alternative if this is a +Failure+.
|
149
149
|
# @return [Try]
|
150
150
|
# @example
|
151
|
-
#
|
152
|
-
#
|
153
|
-
#
|
151
|
+
# Fear.success(42).or_else { Fear.success(-1) } #=> Fear.success(42)
|
152
|
+
# Fear.failure(ArgumentError.new).or_else { Fear.success(-1) } #=> Fear.success(-1)
|
153
|
+
# Fear.failure(ArgumentError.new).or_else { Fear.try { 1/0 } }
|
154
|
+
# #=> Fear.failure(ZeroDivisionError.new('divided by 0'))
|
154
155
|
#
|
155
156
|
# @!method flatten
|
156
157
|
# Transforms a nested +Try+, ie, a +Success+ of +Success+,
|
157
158
|
# into an un-nested +Try+, ie, a +Success+.
|
158
159
|
# @return [Try]
|
159
160
|
# @example
|
160
|
-
#
|
161
|
-
#
|
162
|
-
#
|
163
|
-
#
|
161
|
+
# Fear.success(42).flatten #=> Fear.success(42)
|
162
|
+
# Fear.success(Fear.success(42)).flatten #=> Fear.success(42)
|
163
|
+
# Fear.success(Fear.failure(ArgumentError.new)).flatten #=> Fear.failure(ArgumentError.new)
|
164
|
+
# Fear.failure(ArgumentError.new).flatten { -1 } #=> Fear.failure(ArgumentError.new)
|
164
165
|
#
|
165
166
|
# @!method select(&predicate)
|
166
167
|
# Converts this to a +Failure+ if the predicate is not satisfied.
|
@@ -168,53 +169,69 @@ module Fear
|
|
168
169
|
# @yieldreturn [Boolean]
|
169
170
|
# @return [Try]
|
170
171
|
# @example
|
171
|
-
#
|
172
|
-
# #=>
|
173
|
-
#
|
174
|
-
# #=>
|
175
|
-
#
|
176
|
-
# #=>
|
172
|
+
# Fear.success(42).select { |v| v > 40 }
|
173
|
+
# #=> Fear.success(21)
|
174
|
+
# Fear.success(42).select { |v| v < 40 }
|
175
|
+
# #=> Fear.failure(Fear::NoSuchElementError.new("Predicate does not hold for 42"))
|
176
|
+
# Fear.failure(ArgumentError.new).select { |v| v < 40 }
|
177
|
+
# #=> Fear.failure(ArgumentError.new)
|
177
178
|
#
|
178
179
|
# @!method recover_with(&block)
|
179
180
|
# Applies the given block to exception. This is like +flat_map+
|
180
181
|
# for the exception.
|
181
|
-
# @yieldparam [
|
182
|
-
# @yieldreturn [Try]
|
183
|
-
# @return [Try]
|
182
|
+
# @yieldparam [Fear::PatternMatch] matcher
|
183
|
+
# @yieldreturn [Fear::Try]
|
184
|
+
# @return [Fear::Try]
|
184
185
|
# @example
|
185
|
-
#
|
186
|
-
#
|
187
|
-
#
|
188
|
-
#
|
189
|
-
#
|
190
|
-
#
|
186
|
+
# Fear.success(42).recover_with do |m|
|
187
|
+
# m.case(ZeroDivisionError) { Fear.success(0) }
|
188
|
+
# end #=> Fear.success(42)
|
189
|
+
#
|
190
|
+
# Fear.failure(ArgumentError.new).recover_with do |m|
|
191
|
+
# m.case(ZeroDivisionError) { Fear.success(0) }
|
192
|
+
# m.case(ArgumentError) { |error| Fear.success(error.class.name) }
|
193
|
+
# end #=> Fear.success('ArgumentError')
|
194
|
+
#
|
195
|
+
# # If the block raises error, this new error returned as an result
|
196
|
+
#
|
197
|
+
# Fear.failure(ArgumentError.new).recover_with do |m|
|
198
|
+
# raise
|
199
|
+
# end #=> Fear.failure(RuntimeError)
|
191
200
|
#
|
192
201
|
# @!method recover(&block)
|
193
202
|
# Applies the given block to exception. This is like +map+ for the exception.
|
194
|
-
# @yieldparam [
|
203
|
+
# @yieldparam [Fear::PatternMatch] matcher
|
195
204
|
# @yieldreturn [any]
|
196
|
-
# @return [Try]
|
205
|
+
# @return [Fear::Try]
|
197
206
|
# @example #recover
|
198
|
-
#
|
199
|
-
#
|
200
|
-
#
|
201
|
-
#
|
202
|
-
#
|
203
|
-
#
|
207
|
+
# Fear.success(42).recover do |m|
|
208
|
+
# m.case(&:message)
|
209
|
+
# end #=> Fear.success(42)
|
210
|
+
#
|
211
|
+
# Fear.failure(ArgumentError.new).recover do |m|
|
212
|
+
# m.case(ZeroDivisionError) { 0 }
|
213
|
+
# m.case(&:message)
|
214
|
+
# end #=> Fear.success('ArgumentError')
|
215
|
+
#
|
216
|
+
# # If the block raises error, this new error returned as an result
|
217
|
+
#
|
218
|
+
# Fear.failure(ArgumentError.new).recover do |m|
|
219
|
+
# raise
|
220
|
+
# end #=> Fear.failure(RuntimeError)
|
204
221
|
#
|
205
222
|
# @!method to_either
|
206
223
|
# Returns +Left+ with exception if this is a +Failure+, otherwise
|
207
224
|
# returns +Right+ with +Success+ value.
|
208
225
|
# @return [Right<any>, Left<StandardError>]
|
209
226
|
# @example
|
210
|
-
#
|
211
|
-
#
|
227
|
+
# Fear.success(42).to_either #=> Fear.right(42)
|
228
|
+
# Fear.failure(ArgumentError.new).to_either #=> Fear.left(ArgumentError.new)
|
212
229
|
#
|
213
230
|
# @!method match(&matcher)
|
214
231
|
# Pattern match against this +Try+
|
215
232
|
# @yield matcher [Fear::TryPatternMatch]
|
216
233
|
# @example
|
217
|
-
#
|
234
|
+
# Fear.try { ... }.match do |m|
|
218
235
|
# m.success(Integer) do |x|
|
219
236
|
# x * 2
|
220
237
|
# end
|
@@ -268,34 +285,32 @@ module Fear
|
|
268
285
|
# @example
|
269
286
|
# include Fear::Try::Mixin
|
270
287
|
#
|
271
|
-
#
|
272
|
-
#
|
273
|
-
#
|
288
|
+
# Fear.try { 4/2 } #=> #<Fear::Success value=2>
|
289
|
+
# Fear.try { 4/0 } #=> #<Fear::Failure exception=#<ZeroDivisionError: divided by 0>>
|
290
|
+
# Fear.success(2) #=> #<Fear::Success value=2>
|
274
291
|
#
|
275
292
|
module Mixin
|
276
293
|
# Constructs a +Try+ using the block. This
|
277
|
-
# method
|
294
|
+
# method ensures any non-fatal exception is caught and a
|
278
295
|
# +Failure+ object is returned.
|
279
296
|
# @return [Try]
|
280
297
|
#
|
281
|
-
def Try
|
282
|
-
|
283
|
-
rescue StandardError => error
|
284
|
-
Failure.new(error)
|
298
|
+
def Try(&block)
|
299
|
+
Fear.try(&block)
|
285
300
|
end
|
286
301
|
|
287
302
|
# @param exception [StandardError]
|
288
303
|
# @return [Failure]
|
289
304
|
#
|
290
305
|
def Failure(exception)
|
291
|
-
|
306
|
+
Fear.failure(exception)
|
292
307
|
end
|
293
308
|
|
294
309
|
# @param value [any]
|
295
310
|
# @return [Success]
|
296
311
|
#
|
297
312
|
def Success(value)
|
298
|
-
|
313
|
+
Fear.success(value)
|
299
314
|
end
|
300
315
|
end
|
301
316
|
end
|