fear 2.0.1 → 3.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/workflows/spec.yml +1 -5
- data/CHANGELOG.md +8 -0
- data/Gemfile +14 -2
- data/Gemfile.lock +48 -61
- data/LICENSE.txt +1 -1
- data/README.md +18 -70
- data/Rakefile +32 -119
- data/benchmarks/dry_do_vs_fear_for.txt +7 -6
- data/benchmarks/dry_some_fmap_vs_fear_some_map.txt +7 -6
- data/benchmarks/factorial.txt +7 -9
- data/benchmarks/fear_gaurd_and1_vs_new.txt +7 -6
- data/benchmarks/fear_gaurd_and2_vs_and.txt +8 -7
- data/benchmarks/fear_gaurd_and3_vs_and_and.txt +7 -6
- data/benchmarks/fear_pattern_matching_construction_vs_execution.txt +7 -6
- data/benchmarks/pattern_matching_dry_vs_qo_vs_fear_try.txt +8 -10
- data/fear.gemspec +4 -19
- data/lib/fear/either/left_projection.rb +237 -0
- data/lib/fear/either/pattern_match.rb +49 -0
- data/lib/fear/either.rb +20 -11
- data/lib/fear/either_api.rb +2 -4
- data/lib/fear/empty_partial_function.rb +1 -1
- data/lib/fear/failure/pattern_match.rb +14 -0
- data/lib/fear/failure.rb +1 -1
- data/lib/fear/for_api.rb +0 -2
- data/lib/fear/future.rb +1 -1
- data/lib/fear/future_api.rb +0 -5
- data/lib/fear/left/pattern_match.rb +15 -0
- data/lib/fear/left.rb +1 -1
- data/lib/fear/none.rb +0 -87
- data/lib/fear/none_class/pattern_match.rb +16 -0
- data/lib/fear/none_class.rb +85 -0
- data/lib/fear/option/pattern_match.rb +47 -0
- data/lib/fear/option.rb +1 -5
- data/lib/fear/option_api.rb +1 -3
- data/lib/fear/partial_function/empty.rb +3 -5
- data/lib/fear/partial_function/guard.rb +0 -4
- data/lib/fear/partial_function/or_else.rb +0 -2
- data/lib/fear/partial_function.rb +0 -9
- data/lib/fear/partial_function_class.rb +1 -1
- data/lib/fear/pattern_match.rb +3 -2
- data/lib/fear/pattern_matching_api.rb +0 -3
- data/lib/fear/right/pattern_match.rb +15 -0
- data/lib/fear/right.rb +1 -1
- data/lib/fear/right_biased.rb +2 -0
- data/lib/fear/some/pattern_match.rb +15 -0
- data/lib/fear/some.rb +1 -1
- data/lib/fear/success/pattern_match.rb +16 -0
- data/lib/fear/success.rb +1 -1
- data/lib/fear/try/pattern_match.rb +29 -0
- data/lib/fear/try.rb +3 -7
- data/lib/fear/try_api.rb +0 -2
- data/lib/fear/version.rb +1 -1
- data/lib/fear.rb +3 -14
- data/spec/fear/awaitable_spec.rb +0 -2
- data/spec/fear/either/left_projection_spec.rb +289 -0
- data/spec/fear/{either_pattern_match_spec.rb → either/pattern_match_spec.rb} +1 -1
- data/spec/fear/{option_pattern_match_spec.rb → option/pattern_match_spec.rb} +1 -1
- data/spec/fear/partial_function/empty_spec.rb +1 -1
- data/spec/fear/{try_pattern_match_spec.rb → try/try_pattern_match_spec.rb} +1 -1
- data/spec/support/.keep +0 -0
- metadata +29 -255
- data/benchmarks/fear_pattern_extracting_with_vs_without_cache.txt +0 -11
- data/benchmarks/pattern_matching_qo_vs_fear_pattern_extraction.txt +0 -11
- data/benchmarks/pattern_matching_qo_vs_fear_try_execution.txt +0 -11
- data/lib/dry/types/fear/option.rb +0 -125
- data/lib/dry/types/fear.rb +0 -8
- data/lib/fear/either_pattern_match.rb +0 -52
- data/lib/fear/failure_pattern_match.rb +0 -12
- data/lib/fear/left_pattern_match.rb +0 -11
- data/lib/fear/none_pattern_match.rb +0 -14
- data/lib/fear/option_pattern_match.rb +0 -50
- data/lib/fear/right_pattern_match.rb +0 -13
- data/lib/fear/some_pattern_match.rb +0 -13
- data/lib/fear/struct.rb +0 -237
- data/lib/fear/success_pattern_match.rb +0 -14
- data/lib/fear/try_pattern_match.rb +0 -32
- data/spec/dry/types/fear/option/constrained_spec.rb +0 -22
- data/spec/dry/types/fear/option/core_spec.rb +0 -77
- data/spec/dry/types/fear/option/default_spec.rb +0 -21
- data/spec/dry/types/fear/option/hash_spec.rb +0 -58
- data/spec/dry/types/fear/option/option_spec.rb +0 -97
- data/spec/struct_pattern_matching_spec.rb +0 -36
- data/spec/struct_spec.rb +0 -194
- data/spec/support/dry_types.rb +0 -6
data/lib/fear/none.rb
CHANGED
@@ -1,94 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Fear
|
4
|
-
# @api private
|
5
|
-
class NoneClass
|
6
|
-
include Option
|
7
|
-
include RightBiased::Left
|
8
|
-
include NonePatternMatch.mixin
|
9
|
-
|
10
|
-
# @raise [NoSuchElementError]
|
11
|
-
def get
|
12
|
-
raise NoSuchElementError
|
13
|
-
end
|
14
|
-
|
15
|
-
# @return [nil]
|
16
|
-
def or_nil
|
17
|
-
nil
|
18
|
-
end
|
19
|
-
|
20
|
-
# @return [true]
|
21
|
-
def empty?
|
22
|
-
true
|
23
|
-
end
|
24
|
-
|
25
|
-
alias :blank? :empty?
|
26
|
-
|
27
|
-
# @return [false]
|
28
|
-
def present?
|
29
|
-
false
|
30
|
-
end
|
31
|
-
|
32
|
-
# @return [None]
|
33
|
-
def select(*)
|
34
|
-
self
|
35
|
-
end
|
36
|
-
|
37
|
-
# @return [None]
|
38
|
-
def reject(*)
|
39
|
-
self
|
40
|
-
end
|
41
|
-
|
42
|
-
# @return [String]
|
43
|
-
def inspect
|
44
|
-
"#<Fear::NoneClass>"
|
45
|
-
end
|
46
|
-
|
47
|
-
# @return [String]
|
48
|
-
alias to_s inspect
|
49
|
-
|
50
|
-
# @param other [Any]
|
51
|
-
# @return [Boolean]
|
52
|
-
def ==(other)
|
53
|
-
other.is_a?(NoneClass)
|
54
|
-
end
|
55
|
-
|
56
|
-
# @param other
|
57
|
-
# @return [Boolean]
|
58
|
-
def ===(other)
|
59
|
-
self == other
|
60
|
-
end
|
61
|
-
|
62
|
-
# @param other [Fear::Option]
|
63
|
-
# @return [Fear::Option]
|
64
|
-
def zip(other)
|
65
|
-
if other.is_a?(Option)
|
66
|
-
Fear.none
|
67
|
-
else
|
68
|
-
raise TypeError, "can't zip with #{other.class}"
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
# @return [RightBiased::Left]
|
73
|
-
def filter_map
|
74
|
-
self
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
private_constant(:NoneClass)
|
79
|
-
|
80
4
|
# The only instance of NoneClass
|
81
|
-
# @api private
|
82
5
|
None = NoneClass.new.freeze
|
83
6
|
public_constant :None
|
84
|
-
|
85
|
-
class << NoneClass
|
86
|
-
def new
|
87
|
-
None
|
88
|
-
end
|
89
|
-
|
90
|
-
def inherited(*)
|
91
|
-
raise "you are not allowed to inherit from NoneClass, use Fear::None instead"
|
92
|
-
end
|
93
|
-
end
|
94
7
|
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Fear
|
4
|
+
class NoneClass
|
5
|
+
# @api private
|
6
|
+
class PatternMatch < Option::PatternMatch
|
7
|
+
# @param conditions [<#==>]
|
8
|
+
# @return [Fear::OptionPatternMatch]
|
9
|
+
def some(*conditions)
|
10
|
+
self
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
private_constant :PatternMatch
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Fear
|
4
|
+
# @api private
|
5
|
+
class NoneClass
|
6
|
+
include Option
|
7
|
+
include RightBiased::Left
|
8
|
+
include PatternMatch.mixin
|
9
|
+
|
10
|
+
class << self
|
11
|
+
def inherited(*)
|
12
|
+
raise "you are not allowed to inherit from NoneClass, use Fear::None instead"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
# @raise [NoSuchElementError]
|
17
|
+
def get
|
18
|
+
raise NoSuchElementError
|
19
|
+
end
|
20
|
+
|
21
|
+
# @return [nil]
|
22
|
+
def or_nil
|
23
|
+
nil
|
24
|
+
end
|
25
|
+
|
26
|
+
# @return [true]
|
27
|
+
def empty?
|
28
|
+
true
|
29
|
+
end
|
30
|
+
|
31
|
+
alias :blank? :empty?
|
32
|
+
|
33
|
+
# @return [false]
|
34
|
+
def present?
|
35
|
+
false
|
36
|
+
end
|
37
|
+
|
38
|
+
# @return [None]
|
39
|
+
def select(*)
|
40
|
+
self
|
41
|
+
end
|
42
|
+
|
43
|
+
# @return [None]
|
44
|
+
def reject(*)
|
45
|
+
self
|
46
|
+
end
|
47
|
+
|
48
|
+
# @return [String]
|
49
|
+
def inspect
|
50
|
+
"#<Fear::NoneClass>"
|
51
|
+
end
|
52
|
+
|
53
|
+
# @return [String]
|
54
|
+
alias to_s inspect
|
55
|
+
|
56
|
+
# @param other [Any]
|
57
|
+
# @return [Boolean]
|
58
|
+
def ==(other)
|
59
|
+
other.is_a?(NoneClass)
|
60
|
+
end
|
61
|
+
|
62
|
+
# @param other
|
63
|
+
# @return [Boolean]
|
64
|
+
def ===(other)
|
65
|
+
self == other
|
66
|
+
end
|
67
|
+
|
68
|
+
# @param other [Fear::Option]
|
69
|
+
# @return [Fear::Option]
|
70
|
+
def zip(other)
|
71
|
+
if other.is_a?(Option)
|
72
|
+
Fear.none
|
73
|
+
else
|
74
|
+
raise TypeError, "can't zip with #{other.class}"
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
# @return [RightBiased::Left]
|
79
|
+
def filter_map
|
80
|
+
self
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
private_constant(:NoneClass)
|
85
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Fear
|
4
|
+
module Option
|
5
|
+
# Option pattern matcher
|
6
|
+
#
|
7
|
+
# @example
|
8
|
+
# pattern_match =
|
9
|
+
# Option::PatternMatch.new
|
10
|
+
# .some(Integer) { |x| x * 2 }
|
11
|
+
# .some(String) { |x| x.to_i * 2 }
|
12
|
+
# .none { 'NaN' }
|
13
|
+
# .else { 'error '}
|
14
|
+
#
|
15
|
+
# pattern_match.call(42) => 'NaN'
|
16
|
+
#
|
17
|
+
# @example the same matcher may be defined using block syntax
|
18
|
+
# Option::PatternMatch.new do |m|
|
19
|
+
# m.some(Integer) { |x| x * 2 }
|
20
|
+
# m.some(String) { |x| x.to_i * 2 }
|
21
|
+
# m.none { 'NaN' }
|
22
|
+
# m.else { 'error '}
|
23
|
+
# end
|
24
|
+
#
|
25
|
+
# @note it has two optimized subclasses +Fear::SomePatternMatch+ and +Fear::NonePatternMatch+
|
26
|
+
# @api private
|
27
|
+
class PatternMatch < Fear::PatternMatch
|
28
|
+
# Match against Some
|
29
|
+
#
|
30
|
+
# @param conditions [<#==>]
|
31
|
+
# @return [Fear::Option::PatternMatch]
|
32
|
+
def some(*conditions, &effect)
|
33
|
+
branch = Fear.case(Fear::Some, &:get).and_then(Fear.case(*conditions, &effect))
|
34
|
+
or_else(branch)
|
35
|
+
end
|
36
|
+
|
37
|
+
# Match against None
|
38
|
+
#
|
39
|
+
# @param effect [Proc]
|
40
|
+
# @return [Fear::Option::PatternMatch]
|
41
|
+
def none(&effect)
|
42
|
+
branch = Fear.case(Fear::None, &effect)
|
43
|
+
or_else(branch)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
data/lib/fear/option.rb
CHANGED
@@ -207,7 +207,7 @@ module Fear
|
|
207
207
|
# @yieldparam [OptionPatternMatch]
|
208
208
|
# @return [Fear::PartialFunction]
|
209
209
|
def matcher(&matcher)
|
210
|
-
|
210
|
+
Option::PatternMatch.new(&matcher)
|
211
211
|
end
|
212
212
|
|
213
213
|
def match(value, &block)
|
@@ -258,7 +258,3 @@ 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,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "fear/option"
|
4
|
-
|
5
3
|
module Fear
|
6
4
|
module OptionApi
|
7
5
|
# An +Option+ factory which creates +Some+ if the argument is
|
@@ -29,7 +27,7 @@ module Fear
|
|
29
27
|
Fear::None
|
30
28
|
end
|
31
29
|
|
32
|
-
# @param value [
|
30
|
+
# @param value [Object]
|
33
31
|
# @return [Fear::Some]
|
34
32
|
# @example
|
35
33
|
# Fear.some(17) #=> #<Fear::Some get=17>
|
@@ -1,12 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "fear/empty_partial_function"
|
4
|
-
|
5
3
|
module Fear
|
6
4
|
module PartialFunction
|
7
|
-
|
8
|
-
|
5
|
+
Empty = EmptyPartialFunction.new
|
6
|
+
Empty.freeze
|
9
7
|
|
10
|
-
public_constant :
|
8
|
+
public_constant :Empty
|
11
9
|
end
|
12
10
|
end
|
@@ -1,14 +1,5 @@
|
|
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
|
-
|
12
3
|
module Fear
|
13
4
|
# A partial function is a unary function defined on subset of all possible inputs.
|
14
5
|
# The method +defined_at?+ allows to test dynamically if an arg is in
|
@@ -20,7 +20,7 @@ module Fear
|
|
20
20
|
# is contained in the function domain.
|
21
21
|
# @raise [MatchError] when this partial function is not defined.
|
22
22
|
def call(arg)
|
23
|
-
call_or_else(arg, &PartialFunction::
|
23
|
+
call_or_else(arg, &PartialFunction::Empty)
|
24
24
|
end
|
25
25
|
|
26
26
|
# @param arg [any]
|
data/lib/fear/pattern_match.rb
CHANGED
@@ -37,7 +37,7 @@ module Fear
|
|
37
37
|
|
38
38
|
# @return [Fear::PartialFunction]
|
39
39
|
def new
|
40
|
-
builder = __new__(PartialFunction::
|
40
|
+
builder = __new__(PartialFunction::Empty)
|
41
41
|
yield builder
|
42
42
|
builder.result
|
43
43
|
end
|
@@ -89,12 +89,13 @@ module Fear
|
|
89
89
|
#
|
90
90
|
# @param guards [<#===>]
|
91
91
|
# @param effect [Proc]
|
92
|
-
# @return [Fear::
|
92
|
+
# @return [Fear::PatternMatch]
|
93
93
|
# @see #or_else for details
|
94
94
|
def case(*guards, &effect)
|
95
95
|
or_else(Fear.case(*guards, &effect))
|
96
96
|
end
|
97
97
|
|
98
|
+
# @return [Fear::PatternMatch]
|
98
99
|
# @see Fear::PartialFunction#or_else
|
99
100
|
def or_else(other)
|
100
101
|
self.result = result.or_else(other)
|
data/lib/fear/right.rb
CHANGED
data/lib/fear/right_biased.rb
CHANGED
@@ -70,6 +70,7 @@ module Fear
|
|
70
70
|
yield(value)
|
71
71
|
self
|
72
72
|
end
|
73
|
+
alias apply each
|
73
74
|
|
74
75
|
# Maps the value using given block.
|
75
76
|
#
|
@@ -144,6 +145,7 @@ module Fear
|
|
144
145
|
def each
|
145
146
|
self
|
146
147
|
end
|
148
|
+
alias apply each
|
147
149
|
|
148
150
|
# Ignores the given block and return self.
|
149
151
|
#
|
data/lib/fear/some.rb
CHANGED
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Fear
|
4
|
+
class Success
|
5
|
+
# @api private
|
6
|
+
class PatternMatch < Try::PatternMatch
|
7
|
+
# @param conditions [<#==>]
|
8
|
+
# @return [Fear::TryPatternMatch]
|
9
|
+
def failure(*conditions)
|
10
|
+
self
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
private_constant :PatternMatch
|
15
|
+
end
|
16
|
+
end
|
data/lib/fear/success.rb
CHANGED
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Fear
|
4
|
+
module Try
|
5
|
+
# Try pattern matcher
|
6
|
+
#
|
7
|
+
# @note it has two optimized subclasses +Fear::Success::PatternMatch+ and +Fear::FailurePatternMatch+
|
8
|
+
# @api private
|
9
|
+
class PatternMatch < Fear::PatternMatch
|
10
|
+
# Match against +Fear::Success+
|
11
|
+
#
|
12
|
+
# @param conditions [<#==>]
|
13
|
+
# @return [Fear::Try::PatternMatch]
|
14
|
+
def success(*conditions, &effect)
|
15
|
+
branch = Fear.case(Fear::Success, &:get).and_then(Fear.case(*conditions, &effect))
|
16
|
+
or_else(branch)
|
17
|
+
end
|
18
|
+
|
19
|
+
# Match against +Fear::Failure+
|
20
|
+
#
|
21
|
+
# @param conditions [<#==>]
|
22
|
+
# @return [Fear::Try::PatternMatch]
|
23
|
+
def failure(*conditions, &effect)
|
24
|
+
branch = Fear.case(Fear::Failure, &:exception).and_then(Fear.case(*conditions, &effect))
|
25
|
+
or_else(branch)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/lib/fear/try.rb
CHANGED
@@ -231,7 +231,7 @@ module Fear
|
|
231
231
|
#
|
232
232
|
# @!method match(&matcher)
|
233
233
|
# Pattern match against this +Try+
|
234
|
-
# @yield matcher [Fear::
|
234
|
+
# @yield matcher [Fear::Try::PatternMatch]
|
235
235
|
# @example
|
236
236
|
# Fear.try { ... }.match do |m|
|
237
237
|
# m.success(Integer) do |x|
|
@@ -276,10 +276,10 @@ module Fear
|
|
276
276
|
# end
|
277
277
|
# matcher.call(try)
|
278
278
|
#
|
279
|
-
# @yieldparam [Fear::
|
279
|
+
# @yieldparam [Fear::Try::PatternMatch]
|
280
280
|
# @return [Fear::PartialFunction]
|
281
281
|
def matcher(&matcher)
|
282
|
-
|
282
|
+
Try::PatternMatch.new(&matcher)
|
283
283
|
end
|
284
284
|
end
|
285
285
|
|
@@ -317,7 +317,3 @@ module Fear
|
|
317
317
|
end
|
318
318
|
end
|
319
319
|
end
|
320
|
-
|
321
|
-
require "fear/try_pattern_match"
|
322
|
-
require "fear/success"
|
323
|
-
require "fear/failure"
|
data/lib/fear/try_api.rb
CHANGED
data/lib/fear/version.rb
CHANGED
data/lib/fear.rb
CHANGED
@@ -1,16 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "
|
4
|
-
|
5
|
-
|
6
|
-
require "fear/unit"
|
7
|
-
require "fear/either_api"
|
8
|
-
require "fear/for_api"
|
9
|
-
require "fear/future_api"
|
10
|
-
require "fear/option_api"
|
11
|
-
require "fear/pattern_matching_api"
|
12
|
-
require "fear/try_api"
|
13
|
-
require "fear/version"
|
3
|
+
require "zeitwerk"
|
4
|
+
loader = Zeitwerk::Loader.for_gem
|
5
|
+
loader.setup
|
14
6
|
|
15
7
|
module Fear
|
16
8
|
Error = Class.new(StandardError)
|
@@ -25,9 +17,6 @@ module Fear
|
|
25
17
|
NoSuchElementError = Class.new(Error)
|
26
18
|
public_constant :NoSuchElementError
|
27
19
|
|
28
|
-
PatternSyntaxError = Class.new(Error)
|
29
|
-
public_constant :PatternSyntaxError
|
30
|
-
|
31
20
|
extend EitherApi
|
32
21
|
extend ForApi
|
33
22
|
extend FutureApi
|