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.
- checksums.yaml +4 -4
- data/.github/dependabot.yml +27 -0
- data/.github/workflows/rubocop.yml +2 -2
- data/.github/workflows/spec.yml +1 -1
- data/CHANGELOG.md +13 -0
- data/Gemfile.lock +53 -56
- data/README.md +54 -186
- data/Rakefile +0 -21
- data/examples/pattern_extracting.rb +4 -4
- data/fear.gemspec +2 -4
- data/lib/fear/either.rb +8 -4
- data/lib/fear/either_api.rb +2 -0
- data/lib/fear/either_pattern_match.rb +7 -8
- data/lib/fear/failure.rb +0 -9
- data/lib/fear/failure_pattern_match.rb +2 -0
- data/lib/fear/for_api.rb +2 -0
- data/lib/fear/future.rb +12 -20
- data/lib/fear/future_api.rb +13 -2
- data/lib/fear/left.rb +0 -9
- data/lib/fear/none.rb +7 -9
- data/lib/fear/option.rb +5 -1
- data/lib/fear/option_api.rb +2 -0
- data/lib/fear/option_pattern_match.rb +6 -4
- data/lib/fear/partial_function/empty.rb +2 -0
- data/lib/fear/partial_function/guard.rb +4 -4
- data/lib/fear/partial_function/or_else.rb +2 -0
- data/lib/fear/partial_function.rb +9 -8
- data/lib/fear/pattern_match.rb +0 -10
- data/lib/fear/pattern_matching_api.rb +3 -28
- data/lib/fear/promise.rb +3 -9
- data/lib/fear/right.rb +0 -10
- data/lib/fear/right_biased.rb +1 -1
- data/lib/fear/right_pattern_match.rb +2 -0
- data/lib/fear/some.rb +7 -10
- data/lib/fear/struct.rb +3 -14
- data/lib/fear/success.rb +0 -9
- data/lib/fear/success_pattern_match.rb +2 -0
- data/lib/fear/try.rb +6 -2
- data/lib/fear/try_api.rb +2 -0
- data/lib/fear/try_pattern_match.rb +7 -8
- data/lib/fear/utils.rb +0 -3
- data/lib/fear/version.rb +1 -1
- data/lib/fear.rb +8 -42
- data/spec/fear/awaitable_spec.rb +2 -0
- data/spec/fear/either_spec.rb +26 -0
- data/spec/fear/failure_spec.rb +8 -23
- data/spec/fear/for/mixin_spec.rb +15 -0
- data/spec/fear/future_spec.rb +17 -2
- data/spec/fear/guard_spec.rb +110 -0
- data/spec/fear/left_spec.rb +7 -22
- data/spec/fear/none_spec.rb +11 -17
- data/spec/fear/option_spec.rb +15 -1
- data/spec/fear/partial_function/any_spec.rb +25 -0
- data/spec/fear/partial_function_spec.rb +2 -24
- data/spec/fear/pattern_match_spec.rb +0 -34
- data/spec/fear/promise_spec.rb +4 -6
- data/spec/fear/right_spec.rb +0 -22
- data/spec/fear/some_spec.rb +10 -22
- data/spec/fear/success_spec.rb +0 -22
- data/spec/fear/try/mixin_spec.rb +14 -0
- data/spec/fear/try_api_spec.rb +23 -0
- data/spec/struct_spec.rb +1 -33
- metadata +18 -80
- data/examples/pattern_extracting_ruby2.7.rb +0 -15
- data/lib/fear/extractor/anonymous_array_splat_matcher.rb +0 -10
- data/lib/fear/extractor/any_matcher.rb +0 -17
- data/lib/fear/extractor/array_head_matcher.rb +0 -36
- data/lib/fear/extractor/array_matcher.rb +0 -40
- data/lib/fear/extractor/array_splat_matcher.rb +0 -16
- data/lib/fear/extractor/empty_list_matcher.rb +0 -20
- data/lib/fear/extractor/extractor_matcher.rb +0 -44
- data/lib/fear/extractor/grammar.rb +0 -203
- data/lib/fear/extractor/grammar.treetop +0 -129
- data/lib/fear/extractor/identifier_matcher.rb +0 -18
- data/lib/fear/extractor/matcher/and.rb +0 -38
- data/lib/fear/extractor/matcher.rb +0 -53
- data/lib/fear/extractor/named_array_splat_matcher.rb +0 -17
- data/lib/fear/extractor/pattern.rb +0 -58
- data/lib/fear/extractor/typed_identifier_matcher.rb +0 -26
- data/lib/fear/extractor/value_matcher.rb +0 -19
- data/lib/fear/extractor.rb +0 -112
- data/lib/fear/extractor_api.rb +0 -35
- data/spec/fear/extractor/array_matcher_spec.rb +0 -230
- data/spec/fear/extractor/extractor_matcher_spec.rb +0 -153
- data/spec/fear/extractor/grammar_array_spec.rb +0 -25
- data/spec/fear/extractor/identified_matcher_spec.rb +0 -49
- data/spec/fear/extractor/identifier_matcher_spec.rb +0 -68
- data/spec/fear/extractor/pattern_spec.rb +0 -34
- data/spec/fear/extractor/typed_identifier_matcher_spec.rb +0 -64
- data/spec/fear/extractor/value_matcher_number_spec.rb +0 -79
- data/spec/fear/extractor/value_matcher_string_spec.rb +0 -88
- data/spec/fear/extractor/value_matcher_symbol_spec.rb +0 -71
- data/spec/fear/extractor_api_spec.rb +0 -115
- 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 [
|
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 [
|
99
|
-
# @return [
|
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(
|
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"
|
data/lib/fear/either_api.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
|
# 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,
|
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,
|
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
|
data/lib/fear/for_api.rb
CHANGED
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
|
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(
|
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(
|
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(
|
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(
|
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(
|
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(
|
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(
|
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
|
482
|
-
|
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
|
492
|
-
|
493
|
-
end
|
484
|
+
new { result }
|
485
|
+
.yield_self { |future| Fear::Await.ready(future, 10) }
|
494
486
|
end
|
495
487
|
end
|
496
488
|
end
|
data/lib/fear/future_api.rb
CHANGED
@@ -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
|
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(
|
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"
|
data/lib/fear/option_api.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
|
# 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,
|
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,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,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]
|
data/lib/fear/pattern_match.rb
CHANGED
@@ -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
|
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
|
data/lib/fear/right_biased.rb
CHANGED
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
|
|