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.
Files changed (110) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +0 -1
  3. data/.rubocop.yml +18 -0
  4. data/.travis.yml +0 -3
  5. data/CHANGELOG.md +12 -1
  6. data/Gemfile +1 -0
  7. data/{gemfiles/dry_equalizer_0.2.1.gemfile.lock → Gemfile.lock} +21 -12
  8. data/README.md +594 -241
  9. data/Rakefile +166 -219
  10. data/benchmarks/README.md +1 -0
  11. data/benchmarks/dry_do_vs_fear_for.txt +11 -0
  12. data/benchmarks/dry_some_fmap_vs_fear_some_map.txt +11 -0
  13. data/benchmarks/factorial.txt +16 -0
  14. data/benchmarks/fear_gaurd_and1_vs_new.txt +13 -0
  15. data/benchmarks/fear_gaurd_and2_vs_and.txt +13 -0
  16. data/benchmarks/fear_gaurd_and3_vs_and_and.txt +13 -0
  17. data/benchmarks/fear_pattern_extracting_with_vs_without_cache.txt +11 -0
  18. data/benchmarks/fear_pattern_matching_construction_vs_execution.txt +13 -0
  19. data/benchmarks/pattern_matching_dry_vs_qo_vs_fear_try.txt +14 -0
  20. data/benchmarks/pattern_matching_qo_vs_fear_pattern_extraction.txt +11 -0
  21. data/benchmarks/pattern_matching_qo_vs_fear_try_execution.txt +11 -0
  22. data/examples/pattern_extracting.rb +15 -0
  23. data/examples/pattern_matching_binary_tree_set.rb +96 -0
  24. data/examples/pattern_matching_number_in_words.rb +54 -0
  25. data/fear.gemspec +4 -2
  26. data/lib/fear.rb +21 -4
  27. data/lib/fear/either.rb +77 -59
  28. data/lib/fear/either_api.rb +21 -0
  29. data/lib/fear/empty_partial_function.rb +1 -1
  30. data/lib/fear/extractor.rb +108 -0
  31. data/lib/fear/extractor/anonymous_array_splat_matcher.rb +8 -0
  32. data/lib/fear/extractor/any_matcher.rb +15 -0
  33. data/lib/fear/extractor/array_head_matcher.rb +34 -0
  34. data/lib/fear/extractor/array_matcher.rb +38 -0
  35. data/lib/fear/extractor/array_splat_matcher.rb +14 -0
  36. data/lib/fear/extractor/empty_list_matcher.rb +18 -0
  37. data/lib/fear/extractor/extractor_matcher.rb +42 -0
  38. data/lib/fear/extractor/grammar.rb +201 -0
  39. data/lib/fear/extractor/grammar.treetop +129 -0
  40. data/lib/fear/extractor/identifier_matcher.rb +16 -0
  41. data/lib/fear/extractor/matcher.rb +54 -0
  42. data/lib/fear/extractor/matcher/and.rb +36 -0
  43. data/lib/fear/extractor/named_array_splat_matcher.rb +15 -0
  44. data/lib/fear/extractor/pattern.rb +55 -0
  45. data/lib/fear/extractor/typed_identifier_matcher.rb +24 -0
  46. data/lib/fear/extractor/value_matcher.rb +17 -0
  47. data/lib/fear/extractor_api.rb +33 -0
  48. data/lib/fear/failure.rb +32 -10
  49. data/lib/fear/for.rb +14 -69
  50. data/lib/fear/for_api.rb +66 -0
  51. data/lib/fear/future.rb +414 -0
  52. data/lib/fear/future_api.rb +19 -0
  53. data/lib/fear/left.rb +8 -0
  54. data/lib/fear/none.rb +17 -8
  55. data/lib/fear/option.rb +55 -49
  56. data/lib/fear/option_api.rb +38 -0
  57. data/lib/fear/partial_function.rb +9 -12
  58. data/lib/fear/partial_function/empty.rb +1 -1
  59. data/lib/fear/partial_function/guard.rb +8 -20
  60. data/lib/fear/partial_function/lifted.rb +1 -0
  61. data/lib/fear/partial_function_class.rb +10 -0
  62. data/lib/fear/pattern_match.rb +10 -0
  63. data/lib/fear/pattern_matching_api.rb +35 -11
  64. data/lib/fear/promise.rb +87 -0
  65. data/lib/fear/right.rb +8 -0
  66. data/lib/fear/some.rb +22 -3
  67. data/lib/fear/success.rb +22 -1
  68. data/lib/fear/try.rb +82 -67
  69. data/lib/fear/try_api.rb +31 -0
  70. data/lib/fear/unit.rb +28 -0
  71. data/lib/fear/version.rb +1 -1
  72. data/spec/fear/done_spec.rb +3 -3
  73. data/spec/fear/either/mixin_spec.rb +15 -0
  74. data/spec/fear/either_pattern_match_spec.rb +10 -12
  75. data/spec/fear/extractor/array_matcher_spec.rb +228 -0
  76. data/spec/fear/extractor/extractor_matcher_spec.rb +151 -0
  77. data/spec/fear/extractor/grammar_array_spec.rb +23 -0
  78. data/spec/fear/extractor/identified_matcher_spec.rb +47 -0
  79. data/spec/fear/extractor/identifier_matcher_spec.rb +66 -0
  80. data/spec/fear/extractor/pattern_spec.rb +32 -0
  81. data/spec/fear/extractor/typed_identifier_matcher_spec.rb +62 -0
  82. data/spec/fear/extractor/value_matcher_number_spec.rb +77 -0
  83. data/spec/fear/extractor/value_matcher_string_spec.rb +86 -0
  84. data/spec/fear/extractor/value_matcher_symbol_spec.rb +69 -0
  85. data/spec/fear/extractor_api_spec.rb +113 -0
  86. data/spec/fear/extractor_spec.rb +59 -0
  87. data/spec/fear/failure_spec.rb +73 -13
  88. data/spec/fear/for_spec.rb +35 -35
  89. data/spec/fear/future_spec.rb +466 -0
  90. data/spec/fear/guard_spec.rb +4 -4
  91. data/spec/fear/left_spec.rb +40 -14
  92. data/spec/fear/none_spec.rb +28 -12
  93. data/spec/fear/option/mixin_spec.rb +37 -0
  94. data/spec/fear/option_pattern_match_spec.rb +7 -9
  95. data/spec/fear/partial_function_spec.rb +25 -3
  96. data/spec/fear/pattern_match_spec.rb +33 -1
  97. data/spec/fear/promise_spec.rb +94 -0
  98. data/spec/fear/right_spec.rb +37 -9
  99. data/spec/fear/some_spec.rb +32 -6
  100. data/spec/fear/success_spec.rb +32 -4
  101. data/spec/fear/try/mixin_spec.rb +17 -0
  102. data/spec/fear/try_pattern_match_spec.rb +8 -10
  103. data/spec/spec_helper.rb +1 -1
  104. metadata +115 -20
  105. data/Appraisals +0 -32
  106. data/gemfiles/dry_equalizer_0.1.0.gemfile +0 -8
  107. data/gemfiles/dry_equalizer_0.1.0.gemfile.lock +0 -82
  108. data/gemfiles/dry_equalizer_0.2.1.gemfile +0 -8
  109. data/lib/fear/done.rb +0 -22
  110. data/spec/fear/option_spec.rb +0 -15
@@ -7,6 +7,7 @@ module Fear
7
7
  @pf = pf
8
8
  end
9
9
  attr_reader :pf
10
+ private :pf
10
11
 
11
12
  # @param arg [any]
12
13
  # @return [Fear::Option]
@@ -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.
@@ -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
- # If you pass a Symbol, it will be converted to proc using +#to_proc+ method
40
+ # It's also possible to pass several guardians. All should match to pass
39
41
  #
40
- # m.case(:even?) { |x| "#{x} is even" }
41
- # m.case(:odd?) { |x| "#{x} is odd" }
42
+ # m.case(Integer, :even?.to_proc) { |x| ... }
43
+ # m.case(Integer, :odd?.to_proc) { |x| ... }
42
44
  #
43
- # It's also possible to pass several guardians. All should match to pass
45
+ # If you want to perform pattern destruction, use +#xcase+ method
44
46
  #
45
- # m.case(Integer, :even?) { |x| ... }
46
- # m.case(Integer, :odd?) { |x| ... }
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::PartialFunction]
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?) { |n| "#{n} is even number" }
74
- # m.case(Integer, :odd?) { |n| "#{n} is odd number" }
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?) { |x| x / 2 }
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 [<#===, symbol>]
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
@@ -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
@@ -4,6 +4,14 @@ module Fear
4
4
  include RightBiased::Right
5
5
  include RightPatternMatch.mixin
6
6
 
7
+ EXTRACTOR = proc do |either|
8
+ if Fear::Right === either
9
+ Fear.some([either.right_value])
10
+ else
11
+ Fear.none
12
+ end
13
+ end
14
+
7
15
  # @api private
8
16
  def right_value
9
17
  value
@@ -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
@@ -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
@@ -11,8 +11,8 @@ module Fear
11
11
  # @example
12
12
  # include Fear::Try::Mixin
13
13
  #
14
- # dividend = Try { Integer(params[:dividend]) }
15
- # divisor = Try { Integer(params[: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
- # Success(42).get_or_else { 24/2 } #=> 42
57
- # Failure(ArgumentError.new).get_or_else { 24/2 } #=> 12
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
- # Success(42).get_or_else(12) #=> 42
62
- # Failure(ArgumentError.new).get_or_else(12) #=> 12
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
- # Success(17).include?(17) #=> true
71
- # Success(17).include?(7) #=> false
72
- # Failure(ArgumentError.new).include?(17) #=> false
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
- # Success(17).each do |value|
81
+ # Fear.success(17).each do |value|
82
82
  # puts value
83
83
  # end #=> prints 17
84
84
  #
85
- # Failure(ArgumentError.new).each do |value|
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
- # Success(42).map { |v| v/2 } #=> Success(21)
96
- # Failure(ArgumentError.new).map { |v| v/2 } #=> Failure(ArgumentError.new)
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
- # Success(42).flat_map { |v| Success(v/2) }
106
- # #=> Success(21)
107
- # Failure(ArgumentError.new).flat_map { |v| Success(v/2) }
108
- # #=> Failure(ArgumentError.new)
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
- # Success(42).to_option #=> Some(21)
116
- # Failure(ArgumentError.new).to_option #=> None()
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
- # Success(12).any?( |v| v > 10) #=> true
126
- # Success(7).any?( |v| v > 10) #=> false
127
- # Failure(ArgumentError.new).any?( |v| v > 10) #=> false
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
- # Success(42).get #=> 42
145
- # Failure(ArgumentError.new).get #=> ArgumentError: ArgumentError
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
- # Success(42).or_else { Success(-1) } #=> Success(42)
152
- # Failure(ArgumentError.new).or_else { Success(-1) } #=> Success(-1)
153
- # Failure(ArgumentError.new).or_else { Try { 1/0 } } #=> Failure(ZeroDivisionError.new('divided by 0'))
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
- # Success(42).flatten #=> Success(42)
161
- # Success(Success(42)).flatten #=> Success(42)
162
- # Success(Failure(ArgumentError.new)).flatten #=> Failure(ArgumentError.new)
163
- # Failure(ArgumentError.new).flatten { -1 } #=> Failure(ArgumentError.new)
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
- # Success(42).select { |v| v > 40 }
172
- # #=> Success(21)
173
- # Success(42).select { |v| v < 40 }
174
- # #=> Failure(Fear::NoSuchElementError.new("Predicate does not hold for 42"))
175
- # Failure(ArgumentError.new).select { |v| v < 40 }
176
- # #=> Failure(ArgumentError.new)
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 [Exception] exception
182
- # @yieldreturn [Try]
183
- # @return [Try]
182
+ # @yieldparam [Fear::PatternMatch] matcher
183
+ # @yieldreturn [Fear::Try]
184
+ # @return [Fear::Try]
184
185
  # @example
185
- # Success(42).recover_with { |e| Success(e.massage) }
186
- # #=> Success(42)
187
- # Failure(ArgumentError.new).recover_with { |e| Success(e.massage) }
188
- # #=> Success('ArgumentError')
189
- # Failure(ArgumentError.new).recover_with { |e| raise }
190
- # #=> Failure(RuntimeError)
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 [Exception] exception
203
+ # @yieldparam [Fear::PatternMatch] matcher
195
204
  # @yieldreturn [any]
196
- # @return [Try]
205
+ # @return [Fear::Try]
197
206
  # @example #recover
198
- # Success(42).recover { |e| e.massage }
199
- # #=> Success(42)
200
- # Failure(ArgumentError.new).recover { |e| e.massage }
201
- # #=> Success('ArgumentError')
202
- # Failure(ArgumentError.new).recover { |e| raise }
203
- # #=> Failure(RuntimeError)
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
- # Success(42).to_either #=> Right(42)
211
- # Failure(ArgumentError.new).to_either #=> Left(ArgumentError.new)
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
- # Try { ... }.match do |m|
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
- # Try { 4/2 } #=> #<Fear::Success value=2>
272
- # Try { 4/0 } #=> #<Fear::Failure value=#<ZeroDivisionError: divided by 0>>
273
- # Success(2) #=> #<Fear::Success value=2>
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 will ensure any non-fatal exception )is caught and a
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
- Success.new(yield)
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
- Failure.new(exception)
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
- Success.new(value)
313
+ Fear.success(value)
299
314
  end
300
315
  end
301
316
  end