fear 1.2.0 → 2.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 (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