fear 1.2.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (94) hide show
  1. checksums.yaml +4 -4
  2. data/.github/dependabot.yml +27 -0
  3. data/.github/workflows/rubocop.yml +2 -2
  4. data/.github/workflows/spec.yml +1 -1
  5. data/CHANGELOG.md +13 -0
  6. data/Gemfile.lock +53 -56
  7. data/README.md +54 -186
  8. data/Rakefile +0 -21
  9. data/examples/pattern_extracting.rb +4 -4
  10. data/fear.gemspec +2 -4
  11. data/lib/fear/either.rb +8 -4
  12. data/lib/fear/either_api.rb +2 -0
  13. data/lib/fear/either_pattern_match.rb +7 -8
  14. data/lib/fear/failure.rb +0 -9
  15. data/lib/fear/failure_pattern_match.rb +2 -0
  16. data/lib/fear/for_api.rb +2 -0
  17. data/lib/fear/future.rb +12 -20
  18. data/lib/fear/future_api.rb +13 -2
  19. data/lib/fear/left.rb +0 -9
  20. data/lib/fear/none.rb +7 -9
  21. data/lib/fear/option.rb +5 -1
  22. data/lib/fear/option_api.rb +2 -0
  23. data/lib/fear/option_pattern_match.rb +6 -4
  24. data/lib/fear/partial_function/empty.rb +2 -0
  25. data/lib/fear/partial_function/guard.rb +4 -4
  26. data/lib/fear/partial_function/or_else.rb +2 -0
  27. data/lib/fear/partial_function.rb +9 -8
  28. data/lib/fear/pattern_match.rb +0 -10
  29. data/lib/fear/pattern_matching_api.rb +3 -28
  30. data/lib/fear/promise.rb +3 -9
  31. data/lib/fear/right.rb +0 -10
  32. data/lib/fear/right_biased.rb +1 -1
  33. data/lib/fear/right_pattern_match.rb +2 -0
  34. data/lib/fear/some.rb +7 -10
  35. data/lib/fear/struct.rb +3 -14
  36. data/lib/fear/success.rb +0 -9
  37. data/lib/fear/success_pattern_match.rb +2 -0
  38. data/lib/fear/try.rb +6 -2
  39. data/lib/fear/try_api.rb +2 -0
  40. data/lib/fear/try_pattern_match.rb +7 -8
  41. data/lib/fear/utils.rb +0 -3
  42. data/lib/fear/version.rb +1 -1
  43. data/lib/fear.rb +8 -42
  44. data/spec/fear/awaitable_spec.rb +2 -0
  45. data/spec/fear/either_spec.rb +26 -0
  46. data/spec/fear/failure_spec.rb +8 -23
  47. data/spec/fear/for/mixin_spec.rb +15 -0
  48. data/spec/fear/future_spec.rb +17 -2
  49. data/spec/fear/guard_spec.rb +110 -0
  50. data/spec/fear/left_spec.rb +7 -22
  51. data/spec/fear/none_spec.rb +11 -17
  52. data/spec/fear/option_spec.rb +15 -1
  53. data/spec/fear/partial_function/any_spec.rb +25 -0
  54. data/spec/fear/partial_function_spec.rb +2 -24
  55. data/spec/fear/pattern_match_spec.rb +0 -34
  56. data/spec/fear/promise_spec.rb +4 -6
  57. data/spec/fear/right_spec.rb +0 -22
  58. data/spec/fear/some_spec.rb +10 -22
  59. data/spec/fear/success_spec.rb +0 -22
  60. data/spec/fear/try/mixin_spec.rb +14 -0
  61. data/spec/fear/try_api_spec.rb +23 -0
  62. data/spec/struct_spec.rb +1 -33
  63. metadata +18 -80
  64. data/examples/pattern_extracting_ruby2.7.rb +0 -15
  65. data/lib/fear/extractor/anonymous_array_splat_matcher.rb +0 -10
  66. data/lib/fear/extractor/any_matcher.rb +0 -17
  67. data/lib/fear/extractor/array_head_matcher.rb +0 -36
  68. data/lib/fear/extractor/array_matcher.rb +0 -40
  69. data/lib/fear/extractor/array_splat_matcher.rb +0 -16
  70. data/lib/fear/extractor/empty_list_matcher.rb +0 -20
  71. data/lib/fear/extractor/extractor_matcher.rb +0 -44
  72. data/lib/fear/extractor/grammar.rb +0 -203
  73. data/lib/fear/extractor/grammar.treetop +0 -129
  74. data/lib/fear/extractor/identifier_matcher.rb +0 -18
  75. data/lib/fear/extractor/matcher/and.rb +0 -38
  76. data/lib/fear/extractor/matcher.rb +0 -53
  77. data/lib/fear/extractor/named_array_splat_matcher.rb +0 -17
  78. data/lib/fear/extractor/pattern.rb +0 -58
  79. data/lib/fear/extractor/typed_identifier_matcher.rb +0 -26
  80. data/lib/fear/extractor/value_matcher.rb +0 -19
  81. data/lib/fear/extractor.rb +0 -112
  82. data/lib/fear/extractor_api.rb +0 -35
  83. data/spec/fear/extractor/array_matcher_spec.rb +0 -230
  84. data/spec/fear/extractor/extractor_matcher_spec.rb +0 -153
  85. data/spec/fear/extractor/grammar_array_spec.rb +0 -25
  86. data/spec/fear/extractor/identified_matcher_spec.rb +0 -49
  87. data/spec/fear/extractor/identifier_matcher_spec.rb +0 -68
  88. data/spec/fear/extractor/pattern_spec.rb +0 -34
  89. data/spec/fear/extractor/typed_identifier_matcher_spec.rb +0 -64
  90. data/spec/fear/extractor/value_matcher_number_spec.rb +0 -79
  91. data/spec/fear/extractor/value_matcher_string_spec.rb +0 -88
  92. data/spec/fear/extractor/value_matcher_symbol_spec.rb +0 -71
  93. data/spec/fear/extractor_api_spec.rb +0 -115
  94. data/spec/fear/extractor_spec.rb +0 -61
data/lib/fear/either.rb CHANGED
@@ -72,7 +72,7 @@ module Fear
72
72
  # Performs the given block if this is a +Right+.
73
73
  # @yieldparam [any] value
74
74
  # @yieldreturn [void]
75
- # @return [Option] itself
75
+ # @return [Fear::Either] itself
76
76
  # @example
77
77
  # Fear.right(17).each do |value|
78
78
  # puts value
@@ -95,8 +95,8 @@ module Fear
95
95
  # Returns the given block applied to the value from this +Right+
96
96
  # or returns this if this is a +Left+.
97
97
  # @yieldparam [any] value
98
- # @yieldreturn [Option]
99
- # @return [Option]
98
+ # @yieldreturn [Fear::Either]
99
+ # @return [Fear::Either]
100
100
  # @example
101
101
  # Fear.right(42).flat_map { |v| Fear.right(v/2) } #=> Fear.right(21)
102
102
  # Fear.left('undefined').flat_map { |v| Fear.right(v/2) } #=> Fear.left('undefined')
@@ -106,7 +106,7 @@ module Fear
106
106
  # this is a +Left+.
107
107
  # @return [Option]
108
108
  # @example
109
- # Fear.right(42).to_option #=> Fear.some(21)
109
+ # Fear.right(42).to_option #=> Fear.some(42)
110
110
  # Fear.left('undefined').to_option #=> Fear.none()
111
111
  #
112
112
  # @!method any?(&predicate)
@@ -331,3 +331,7 @@ module Fear
331
331
  end
332
332
  end
333
333
  end
334
+
335
+ require "fear/either_pattern_match"
336
+ require "fear/left"
337
+ require "fear/right"
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "fear/either"
4
+
3
5
  module Fear
4
6
  module EitherApi
5
7
  # @param value [any]
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "fear/pattern_match"
4
+
3
5
  module Fear
4
6
  # Either pattern matcher
5
7
  #
@@ -24,18 +26,12 @@ module Fear
24
26
  # @note it has two optimized subclasses +Fear::LeftPatternMatch+ and +Fear::RightPatternMatch+
25
27
  # @api private
26
28
  class EitherPatternMatch < Fear::PatternMatch
27
- LEFT_EXTRACTOR = :left_value.to_proc
28
- public_constant :LEFT_EXTRACTOR
29
-
30
- RIGHT_EXTRACTOR = :right_value.to_proc
31
- public_constant :RIGHT_EXTRACTOR
32
-
33
29
  # Match against +Fear::Right+
34
30
  #
35
31
  # @param conditions [<#==>]
36
32
  # @return [Fear::EitherPatternMatch]
37
33
  def right(*conditions, &effect)
38
- branch = Fear.case(Fear::Right, &RIGHT_EXTRACTOR).and_then(Fear.case(*conditions, &effect))
34
+ branch = Fear.case(Fear::Right, &:right_value).and_then(Fear.case(*conditions, &effect))
39
35
  or_else(branch)
40
36
  end
41
37
  alias success right
@@ -45,9 +41,12 @@ module Fear
45
41
  # @param conditions [<#==>]
46
42
  # @return [Fear::EitherPatternMatch]
47
43
  def left(*conditions, &effect)
48
- branch = Fear.case(Fear::Left, &LEFT_EXTRACTOR).and_then(Fear.case(*conditions, &effect))
44
+ branch = Fear.case(Fear::Left, &:left_value).and_then(Fear.case(*conditions, &effect))
49
45
  or_else(branch)
50
46
  end
51
47
  alias failure left
52
48
  end
53
49
  end
50
+
51
+ require "fear/left_pattern_match"
52
+ require "fear/right_pattern_match"
data/lib/fear/failure.rb CHANGED
@@ -6,15 +6,6 @@ module Fear
6
6
  include RightBiased::Left
7
7
  include FailurePatternMatch.mixin
8
8
 
9
- EXTRACTOR = proc do |try|
10
- if Fear::Failure === try
11
- Fear.some([try.exception])
12
- else
13
- Fear.none
14
- end
15
- end
16
- public_constant :EXTRACTOR
17
-
18
9
  # @param [StandardError]
19
10
  def initialize(exception)
20
11
  @exception = exception
@@ -7,4 +7,6 @@ module Fear
7
7
  self
8
8
  end
9
9
  end
10
+
11
+ private_constant :FailurePatternMatch
10
12
  end
data/lib/fear/for_api.rb CHANGED
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "fear/for"
4
+
3
5
  module Fear
4
6
  module ForApi
5
7
  # Syntactic sugar for composition of multiple monadic operations. It supports two such
data/lib/fear/future.rb CHANGED
@@ -1,11 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- begin
4
- require "concurrent"
5
- rescue LoadError
6
- puts "You must add 'concurrent-ruby' to your Gemfile in order to use Fear::Future"
7
- end
8
-
9
3
  module Fear
10
4
  # Asynchronous computations that yield futures are created
11
5
  # with the +Fear.future+ call:
@@ -61,7 +55,7 @@ module Fear
61
55
  #
62
56
  def initialize(promise = nil, **options, &block)
63
57
  if block_given? && promise
64
- raise ArgumentError, "pass block or future"
58
+ raise ArgumentError, "pass block or promise"
65
59
  end
66
60
 
67
61
  @options = options
@@ -249,7 +243,7 @@ module Fear
249
243
  # )
250
244
  #
251
245
  def transform(success, failure)
252
- promise = Promise.new(@options)
246
+ promise = Promise.new(**@options)
253
247
  on_complete_match do |m|
254
248
  m.success { |value| promise.success(success.(value)) }
255
249
  m.failure { |error| promise.failure(failure.(error)) }
@@ -268,7 +262,7 @@ module Fear
268
262
  # future.map { |v| v * 2 } #=> the same as Fear.future { 2 * 2 }
269
263
  #
270
264
  def map(&block)
271
- promise = Promise.new(@options)
265
+ promise = Promise.new(**@options)
272
266
  on_complete do |try|
273
267
  promise.complete!(try.map(&block))
274
268
  end
@@ -294,7 +288,7 @@ module Fear
294
288
  # end
295
289
  #
296
290
  def flat_map
297
- promise = Promise.new(@options)
291
+ promise = Promise.new(**@options)
298
292
  on_complete_match do |m|
299
293
  m.case(Fear::Failure) { |failure| promise.complete!(failure) }
300
294
  m.success do |value|
@@ -348,7 +342,7 @@ module Fear
348
342
  #
349
343
  #
350
344
  def recover(&block)
351
- promise = Promise.new(@options)
345
+ promise = Promise.new(**@options)
352
346
  on_complete do |try|
353
347
  promise.complete!(try.recover(&block))
354
348
  end
@@ -374,7 +368,7 @@ module Fear
374
368
  # # but it performs two calls asynchronously
375
369
  #
376
370
  def zip(other)
377
- promise = Promise.new(@options)
371
+ promise = Promise.new(**@options)
378
372
  on_complete_match do |m|
379
373
  m.success do |value|
380
374
  other.on_complete do |other_try|
@@ -412,7 +406,7 @@ module Fear
412
406
  # f.fallback_to(g) # evaluates to 5
413
407
  #
414
408
  def fallback_to(fallback)
415
- promise = Promise.new(@options)
409
+ promise = Promise.new(**@options)
416
410
  on_complete_match do |m|
417
411
  m.success { |value| promise.complete!(value) }
418
412
  m.failure do |error|
@@ -447,7 +441,7 @@ module Fear
447
441
  # end
448
442
  #
449
443
  def and_then
450
- promise = Promise.new(@options)
444
+ promise = Promise.new(**@options)
451
445
  on_complete do |try|
452
446
  Fear.try do
453
447
  Fear::Try.matcher { |m| yield(m) }.call_or_else(try, &:itself)
@@ -478,9 +472,8 @@ module Fear
478
472
  # @return [Fear::Future]
479
473
  #
480
474
  def failed(exception)
481
- new(executor: Concurrent::ImmediateExecutor.new) do
482
- raise exception
483
- end
475
+ new { raise exception }
476
+ .yield_self { |future| Fear::Await.ready(future, 10) }
484
477
  end
485
478
 
486
479
  # Creates an already completed +Future+ with the specified result.
@@ -488,9 +481,8 @@ module Fear
488
481
  # @return [Fear::Future]
489
482
  #
490
483
  def successful(result)
491
- new(executor: Concurrent::ImmediateExecutor.new) do
492
- result
493
- end
484
+ new { result }
485
+ .yield_self { |future| Fear::Await.ready(future, 10) }
494
486
  end
495
487
  end
496
488
  end
@@ -1,5 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ begin
4
+ require "concurrent"
5
+ rescue LoadError
6
+ puts "You must add 'concurrent-ruby' to your Gemfile in order to use Fear::Future"
7
+ end
8
+
9
+ require "fear/awaitable"
10
+ require "fear/await"
11
+ require "fear/future"
12
+ require "fear/promise"
13
+
3
14
  module Fear
4
15
  # rubocop: disable Layout/LineLength
5
16
  module FutureApi
@@ -13,8 +24,8 @@ module Fear
13
24
  # f = Fear.future(executor: :io) { open('http://example.com') }
14
25
  # f.map(&:read).each { |body| puts body }
15
26
  #
16
- def future(options = {}, &block)
17
- Future.new(options, &block)
27
+ def future(**options, &block)
28
+ Future.new(nil, **options, &block)
18
29
  end
19
30
  end
20
31
  # rubocop: enable Layout/LineLength
data/lib/fear/left.rb CHANGED
@@ -6,15 +6,6 @@ module Fear
6
6
  include RightBiased::Left
7
7
  include LeftPatternMatch.mixin
8
8
 
9
- EXTRACTOR = proc do |either|
10
- if Fear::Left === either
11
- Fear.some([either.left_value])
12
- else
13
- Fear.none
14
- end
15
- end
16
- public_constant :EXTRACTOR
17
-
18
9
  # @api private
19
10
  def left_value
20
11
  value
data/lib/fear/none.rb CHANGED
@@ -7,15 +7,6 @@ module Fear
7
7
  include RightBiased::Left
8
8
  include NonePatternMatch.mixin
9
9
 
10
- EXTRACTOR = proc do |option|
11
- if Fear::None === option
12
- Fear.some([])
13
- else
14
- Fear.none
15
- end
16
- end
17
- public_constant :EXTRACTOR
18
-
19
10
  # @raise [NoSuchElementError]
20
11
  def get
21
12
  raise NoSuchElementError
@@ -31,6 +22,13 @@ module Fear
31
22
  true
32
23
  end
33
24
 
25
+ alias :blank? :empty?
26
+
27
+ # @return [false]
28
+ def present?
29
+ false
30
+ end
31
+
34
32
  # @return [None]
35
33
  def select(*)
36
34
  self
data/lib/fear/option.rb CHANGED
@@ -121,7 +121,7 @@ module Fear
121
121
  # @yieldreturn [Boolean]
122
122
  # @return [Option]
123
123
  # @example
124
- # Fear.some(42).select { |v| v > 40 } #=> Fear.success(21)
124
+ # Fear.some(42).select { |v| v > 40 } #=> Fear.success(42)
125
125
  # Fear.some(42).select { |v| v < 40 } #=> None
126
126
  # Fear.none.select { |v| v < 40 } #=> None
127
127
  #
@@ -258,3 +258,7 @@ module Fear
258
258
  end
259
259
  end
260
260
  end
261
+
262
+ require "fear/option_pattern_match"
263
+ require "fear/some"
264
+ require "fear/none"
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "fear/option"
4
+
3
5
  module Fear
4
6
  module OptionApi
5
7
  # An +Option+ factory which creates +Some+ if the argument is
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "fear/pattern_match"
4
+
3
5
  module Fear
4
6
  # Option pattern matcher
5
7
  #
@@ -24,15 +26,12 @@ module Fear
24
26
  # @note it has two optimized subclasses +Fear::SomePatternMatch+ and +Fear::NonePatternMatch+
25
27
  # @api private
26
28
  class OptionPatternMatch < Fear::PatternMatch
27
- GET_METHOD = :get.to_proc
28
- private_constant :GET_METHOD
29
-
30
29
  # Match against Some
31
30
  #
32
31
  # @param conditions [<#==>]
33
32
  # @return [Fear::OptionPatternMatch]
34
33
  def some(*conditions, &effect)
35
- branch = Fear.case(Fear::Some, &GET_METHOD).and_then(Fear.case(*conditions, &effect))
34
+ branch = Fear.case(Fear::Some, &:get).and_then(Fear.case(*conditions, &effect))
36
35
  or_else(branch)
37
36
  end
38
37
 
@@ -46,3 +45,6 @@ module Fear
46
45
  end
47
46
  end
48
47
  end
48
+
49
+ require "fear/some_pattern_match"
50
+ require "fear/none_pattern_match"
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "fear/empty_partial_function"
4
+
3
5
  module Fear
4
6
  module PartialFunction
5
7
  EMPTY = EmptyPartialFunction.new
@@ -1,15 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "fear/partial_function/guard/or"
4
+ require "fear/partial_function/guard/and"
5
+ require "fear/partial_function/guard/and3"
6
+
3
7
  module Fear
4
8
  module PartialFunction
5
9
  # Guard represents PartialFunction guardian
6
10
  #
7
11
  # @api private
8
12
  class Guard
9
- autoload :And, "fear/partial_function/guard/and"
10
- autoload :And3, "fear/partial_function/guard/and3"
11
- autoload :Or, "fear/partial_function/guard/or"
12
-
13
13
  class << self
14
14
  # Optimized version for combination of two guardians
15
15
  # Two guarding is a very common situation. For example checking for Some, and checking
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "fear/utils"
4
+
3
5
  module Fear
4
6
  module PartialFunction
5
7
  # Composite function produced by +PartialFunction#or_else+ method
@@ -1,5 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "fear/partial_function/and_then"
4
+ require "fear/partial_function/any"
5
+ require "fear/partial_function/combined"
6
+ require "fear/partial_function/empty"
7
+ require "fear/partial_function/guard"
8
+ require "fear/partial_function/lifted"
9
+ require "fear/partial_function/or_else"
10
+ require "fear/partial_function_class"
11
+
3
12
  module Fear
4
13
  # A partial function is a unary function defined on subset of all possible inputs.
5
14
  # The method +defined_at?+ allows to test dynamically if an arg is in
@@ -45,14 +54,6 @@ module Fear
45
54
  # @return [#call]
46
55
  # @abstract
47
56
  module PartialFunction
48
- autoload :AndThen, "fear/partial_function/and_then"
49
- autoload :Any, "fear/partial_function/any"
50
- autoload :Combined, "fear/partial_function/combined"
51
- autoload :EMPTY, "fear/partial_function/empty"
52
- autoload :Guard, "fear/partial_function/guard"
53
- autoload :Lifted, "fear/partial_function/lifted"
54
- autoload :OrElse, "fear/partial_function/or_else"
55
-
56
57
  # Checks if a value is contained in the function's domain.
57
58
  #
58
59
  # @param arg [any]
@@ -95,16 +95,6 @@ module Fear
95
95
  or_else(Fear.case(*guards, &effect))
96
96
  end
97
97
 
98
- # @param pattern [String]
99
- # @param guards [<#===>]
100
- # @param effect [Proc]
101
- # @return [Fear::PartialFunction]
102
- # @see #case for details
103
- # @see Fear.xcase for details
104
- def xcase(pattern, *guards, &effect)
105
- or_else(Fear.xcase(pattern, *guards, &effect))
106
- end
107
-
108
98
  # @see Fear::PartialFunction#or_else
109
99
  def or_else(other)
110
100
  self.result = result.or_else(other)
@@ -1,5 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "fear/partial_function"
4
+ require "fear/pattern_match"
5
+
3
6
  module Fear
4
7
  # @api private
5
8
  module PatternMatchingApi
@@ -44,12 +47,6 @@ module Fear
44
47
  # m.case(Integer, :even?.to_proc) { |x| ... }
45
48
  # m.case(Integer, :odd?.to_proc) { |x| ... }
46
49
  #
47
- # If you want to perform pattern destruction, use +#xcase+ method
48
- #
49
- # m.xcase('Date(year, 12, 31)') { |year:| "Last day of the year #{year}" }
50
- #
51
- # The pattern above ensures that it's 31 of December and extracts year to block named parameter
52
- #
53
50
  # Since matcher returns +Fear::PartialFunction+, you can combine matchers using
54
51
  # partial function API:
55
52
  #
@@ -111,27 +108,5 @@ module Fear
111
108
  def case(*guards, &function)
112
109
  PartialFunction.and(*guards, &function)
113
110
  end
114
-
115
- # Creates partial function defined on domain described with guard
116
- # and perform pattern extraction.
117
- #
118
- # @param pattern [String] pattern to match against
119
- # @param guards [<#===>] other guards against extracted pattern
120
- # @yieldparam hash [{Symbol => any}]
121
- # @return [Fear::PartialFunction]
122
- #
123
- # @example
124
- # pf = Fear.xcase('['ok', Some(body)]') { |body:| ... }
125
- # pf.defined_at?(['ok', Fear.some(body)]) #=> true
126
- # pf.defined_at?(['err', Fear.none]) #=> false
127
- #
128
- # @example pattern and guards. It matches against non-empty body
129
- #
130
- # pf = Fear.xcase('['ok', Some(body)]', ->(body:) { !body.empty? }) { }
131
- #
132
- def xcase(pattern, *guards, &function)
133
- warn "NOTE: Fear.xcase is deprecated and will be removed in a future version. Use `case .. in ..` instead."
134
- Fear[pattern].and_then(self.case(*guards, &function))
135
- end
136
111
  end
137
112
  end
data/lib/fear/promise.rb CHANGED
@@ -1,16 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- begin
4
- require "concurrent"
5
- rescue LoadError
6
- puts "You must add 'concurrent-ruby' to your Gemfile in order to use Fear::Future"
7
- end
8
-
9
3
  module Fear
10
4
  # @api private
11
5
  class Promise < Concurrent::IVar
12
6
  # @param options [Hash] options passed to underlying +Concurrent::Promise+
13
- def initialize(**options)
7
+ def initialize(*_, **options)
14
8
  super()
15
9
  @options = options
16
10
  @promise = Concurrent::Promise.new(options) do
@@ -27,7 +21,7 @@ module Fear
27
21
 
28
22
  # @return [Fear::Future]
29
23
  def to_future
30
- Future.new(promise, options)
24
+ Future.new(promise, **options)
31
25
  end
32
26
 
33
27
  # Complete this promise with successful result
@@ -38,7 +32,7 @@ module Fear
38
32
  complete(Fear.success(value))
39
33
  end
40
34
 
41
- # Complete this promise with failure
35
+ # Complete this promise with value
42
36
  # @param value [any]
43
37
  # @return [self]
44
38
  # @raise [IllegalStateException]
data/lib/fear/right.rb CHANGED
@@ -6,16 +6,6 @@ module Fear
6
6
  include RightBiased::Right
7
7
  include RightPatternMatch.mixin
8
8
 
9
- EXTRACTOR = proc do |either|
10
- if Fear::Right === either
11
- Fear.some([either.right_value])
12
- else
13
- Fear.none
14
- end
15
- end
16
-
17
- public_constant :EXTRACTOR
18
-
19
9
  # @api private
20
10
  def right_value
21
11
  value
@@ -111,7 +111,7 @@ module Fear
111
111
 
112
112
  module Left
113
113
  prepend Interface
114
- include Utils
114
+
115
115
  # @!method get_or_else(default)
116
116
  # @param default [any]
117
117
  # @return [any] default value
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "fear/either_pattern_match"
4
+
3
5
  module Fear
4
6
  # @api private
5
7
  class RightPatternMatch < EitherPatternMatch
data/lib/fear/some.rb CHANGED
@@ -6,16 +6,6 @@ module Fear
6
6
  include RightBiased::Right
7
7
  include SomePatternMatch.mixin
8
8
 
9
- EXTRACTOR = proc do |option|
10
- if Fear::Some === option
11
- Fear.some([option.get])
12
- else
13
- Fear.none
14
- end
15
- end
16
-
17
- public_constant :EXTRACTOR
18
-
19
9
  attr_reader :value
20
10
  protected :value
21
11
 
@@ -38,6 +28,13 @@ module Fear
38
28
  false
39
29
  end
40
30
 
31
+ alias :blank? :empty?
32
+
33
+ # @return [true]
34
+ def present?
35
+ true
36
+ end
37
+
41
38
  # @return [Option]
42
39
  def select
43
40
  if yield(value)
data/lib/fear/struct.rb CHANGED
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "fear/pattern_match"
4
+
3
5
  module Fear
4
6
  # Structs are like regular classes and good for modeling immutable data.
5
7
  #
@@ -36,18 +38,6 @@ module Fear
36
38
  # john.admin #=> false
37
39
  # admin_john.admin #=> true
38
40
  #
39
- # It's possible to match against struct attributes. The following example extracts email from
40
- # user only if user is admin
41
- #
42
- # john = User.new(id: 2, email: 'john@example.com', admin: false)
43
- # john.match |m|
44
- # m.xcase('Fear::Struct(_, email, true)') do |email|
45
- # email
46
- # end
47
- # end
48
- #
49
- # Note, parameters got extracted in order they was defined.
50
- #
51
41
  class Struct
52
42
  include PatternMatch.mixin
53
43
 
@@ -58,7 +48,6 @@ module Fear
58
48
  # @api private
59
49
  def inherited(base)
60
50
  base.instance_variable_set(:@attributes, attributes)
61
- Fear.register_extractor(base, Fear.case(base, &:to_a).lift)
62
51
  end
63
52
 
64
53
  # Defines attribute
@@ -132,7 +121,7 @@ module Fear
132
121
  # admin_john.admin #=> true
133
122
  #
134
123
  def copy(**attributes)
135
- self.class.new(to_h.merge(attributes))
124
+ self.class.new(**to_h.merge(attributes))
136
125
  end
137
126
 
138
127
  # Returns the struct attributes as an array of symbols
data/lib/fear/success.rb CHANGED
@@ -6,15 +6,6 @@ module Fear
6
6
  include RightBiased::Right
7
7
  include SuccessPatternMatch.mixin
8
8
 
9
- EXTRACTOR = proc do |try|
10
- if Fear::Success === try
11
- Fear.some([try.get])
12
- else
13
- Fear.none
14
- end
15
- end
16
- public_constant :EXTRACTOR
17
-
18
9
  attr_reader :value
19
10
  protected :value
20
11
 
@@ -9,4 +9,6 @@ module Fear
9
9
  self
10
10
  end
11
11
  end
12
+
13
+ private_constant :SuccessPatternMatch
12
14
  end