fear 0.11.0 → 1.0.0

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