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
@@ -1,13 +1,14 @@
|
|
1
1
|
# It verifies that optimization for Partial Functions with only one guard actually works.
|
2
2
|
|
3
3
|
> bundle exec rake perf:fear:guard:and1_vs_new
|
4
|
+
ruby 3.3.0 (2023-12-25 revision 5124f9ac75) [arm64-darwin23]
|
4
5
|
Warming up --------------------------------------
|
5
|
-
Guard.new
|
6
|
-
Guard.and1
|
6
|
+
Guard.new 571.139B i/100ms
|
7
|
+
Guard.and1 1.884T i/100ms
|
7
8
|
Calculating -------------------------------------
|
8
|
-
Guard.new
|
9
|
-
Guard.and1
|
9
|
+
Guard.new 2.927Q (±10.3%) i/s - 14.393Q in 4.993407s
|
10
|
+
Guard.and1 32.583Q (± 2.2%) i/s - 162.090Q in 4.977493s
|
10
11
|
|
11
12
|
Comparison:
|
12
|
-
Guard.and1:
|
13
|
-
Guard.new:
|
13
|
+
Guard.and1: 32583184202679384.0 i/s
|
14
|
+
Guard.new: 2927179441726049.0 i/s - 11.13x slower
|
@@ -1,13 +1,14 @@
|
|
1
1
|
# It verifies that optimization for Partial Functions with two guards actually works.
|
2
2
|
|
3
|
-
> bundle exec rake perf:fear:guard:
|
3
|
+
> bundle exec rake perf:fear:guard:and2_vs_and
|
4
|
+
ruby 3.3.0 (2023-12-25 revision 5124f9ac75) [arm64-darwin23]
|
4
5
|
Warming up --------------------------------------
|
5
|
-
and2
|
6
|
-
Guard#and
|
6
|
+
and2 807.325B i/100ms
|
7
|
+
Guard#and 692.737B i/100ms
|
7
8
|
Calculating -------------------------------------
|
8
|
-
and2
|
9
|
-
Guard#and
|
9
|
+
and2 6.011Q (± 2.4%) i/s - 29.972Q in 4.989608s
|
10
|
+
Guard#and 4.443Q (± 2.1%) i/s - 22.168Q in 4.991463s
|
10
11
|
|
11
12
|
Comparison:
|
12
|
-
and2:
|
13
|
-
Guard#and:
|
13
|
+
and2: 6011198087717350.0 i/s
|
14
|
+
Guard#and: 4443444774459918.5 i/s - 1.35x slower
|
@@ -1,13 +1,14 @@
|
|
1
1
|
# It verifies that optimization for Partial Functions with three guards actually works.
|
2
2
|
|
3
3
|
> bundle exec rake perf:fear:guard:and3_vs_and_and
|
4
|
+
ruby 3.3.0 (2023-12-25 revision 5124f9ac75) [arm64-darwin23]
|
4
5
|
Warming up --------------------------------------
|
5
|
-
Guard.and3
|
6
|
-
Guard#and
|
6
|
+
Guard.and3 580.401B i/100ms
|
7
|
+
Guard#and 350.896B i/100ms
|
7
8
|
Calculating -------------------------------------
|
8
|
-
Guard.and3
|
9
|
-
Guard#and
|
9
|
+
Guard.and3 3.152Q (± 1.3%) i/s - 15.736Q in 4.993183s
|
10
|
+
Guard#and 1.132Q (± 1.7%) i/s - 5.653Q in 4.996181s
|
10
11
|
|
11
12
|
Comparison:
|
12
|
-
Guard.and3:
|
13
|
-
Guard#and:
|
13
|
+
Guard.and3: 3152131160662449.0 i/s
|
14
|
+
Guard#and: 1131877273526757.5 i/s - 2.78x slower
|
@@ -1,13 +1,14 @@
|
|
1
1
|
# So, it's better to avoid building pattern match in runtime
|
2
2
|
|
3
3
|
> bundle exec rake perf:fear:pattern_matching_construction_vs_execution
|
4
|
+
ruby 3.3.0 (2023-12-25 revision 5124f9ac75) [arm64-darwin23]
|
4
5
|
Warming up --------------------------------------
|
5
|
-
construction
|
6
|
-
execution
|
6
|
+
construction 53.068k i/100ms
|
7
|
+
execution 280.541k i/100ms
|
7
8
|
Calculating -------------------------------------
|
8
|
-
construction
|
9
|
-
execution
|
9
|
+
construction 537.049k (± 0.2%) i/s - 2.706M in 5.039544s
|
10
|
+
execution 2.799M (± 0.4%) i/s - 14.027M in 5.011175s
|
10
11
|
|
11
12
|
Comparison:
|
12
|
-
execution:
|
13
|
-
construction:
|
13
|
+
execution: 2799195.6 i/s
|
14
|
+
construction: 537049.0 i/s - 5.21x slower
|
@@ -1,14 +1,12 @@
|
|
1
|
-
> bundle exec rake perf:pattern_matching:
|
1
|
+
> bundle exec rake perf:pattern_matching:dry_vs_fear_try
|
2
|
+
ruby 3.3.0 (2023-12-25 revision 5124f9ac75) [arm64-darwin23]
|
2
3
|
Warming up --------------------------------------
|
3
|
-
|
4
|
-
|
5
|
-
Dr::Matcher 13.079k i/100ms
|
4
|
+
Fear 18.527k i/100ms
|
5
|
+
Dr::Matcher 40.145k i/100ms
|
6
6
|
Calculating -------------------------------------
|
7
|
-
|
8
|
-
|
9
|
-
Dr::Matcher 166.700k (± 3.0%) i/s - 837.056k in 5.026408s
|
7
|
+
Fear 187.617k (± 0.4%) i/s - 944.877k in 5.036258s
|
8
|
+
Dr::Matcher 395.181k (± 1.9%) i/s - 2.007M in 5.081136s
|
10
9
|
|
11
10
|
Comparison:
|
12
|
-
Dr::Matcher:
|
13
|
-
Fear:
|
14
|
-
Qo: 38871.9 i/s - 4.29x slower
|
11
|
+
Dr::Matcher: 395181.1 i/s
|
12
|
+
Fear: 187617.3 i/s - 2.11x slower
|
data/fear.gemspec
CHANGED
@@ -8,8 +8,8 @@ require "fear/version"
|
|
8
8
|
Gem::Specification.new do |spec|
|
9
9
|
spec.name = "fear"
|
10
10
|
spec.version = Fear::VERSION
|
11
|
-
spec.authors = ["
|
12
|
-
spec.email = ["
|
11
|
+
spec.authors = ["Tëma Bolshakov"]
|
12
|
+
spec.email = ["tema@bolshakov.dev"]
|
13
13
|
spec.summary = "%q{Ruby port of some Scala's monads.}"
|
14
14
|
spec.description = "Ruby port of some Scala's monads."
|
15
15
|
spec.homepage = "https://github.com/bolshakov/fear"
|
@@ -19,22 +19,7 @@ Gem::Specification.new do |spec|
|
|
19
19
|
spec.executables = spec.files.grep(%r{^bin\/}) { |f| File.basename(f) }
|
20
20
|
spec.test_files = spec.files.grep(%r{^spec\/})
|
21
21
|
spec.require_paths = ["lib"]
|
22
|
-
spec.required_ruby_version = Gem::Requirement.new(">=
|
22
|
+
spec.required_ruby_version = Gem::Requirement.new(">= 3.1")
|
23
23
|
|
24
|
-
spec.
|
25
|
-
spec.add_development_dependency "bundler"
|
26
|
-
spec.add_development_dependency "concurrent-ruby"
|
27
|
-
spec.add_development_dependency "dry-matcher"
|
28
|
-
spec.add_development_dependency "dry-monads"
|
29
|
-
spec.add_development_dependency "qo"
|
30
|
-
spec.add_development_dependency "rake", "~> 13.0"
|
31
|
-
spec.add_development_dependency "rspec", "~> 3.1"
|
32
|
-
spec.add_development_dependency "rubocop-rspec", "1.34.0"
|
33
|
-
spec.add_development_dependency "rubocop", "1.32.0"
|
34
|
-
spec.add_development_dependency "ruby_coding_standard"
|
35
|
-
spec.add_development_dependency "yard"
|
36
|
-
spec.add_development_dependency "dry-types"
|
37
|
-
spec.add_development_dependency "fear-rspec"
|
38
|
-
spec.add_development_dependency "simplecov"
|
39
|
-
spec.add_development_dependency "simplecov-lcov"
|
24
|
+
spec.add_runtime_dependency "zeitwerk"
|
40
25
|
end
|
@@ -0,0 +1,237 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Fear
|
4
|
+
module Either
|
5
|
+
# Projects an `Either` into a `Left`.
|
6
|
+
# @see Fear::Either#left
|
7
|
+
#
|
8
|
+
class LeftProjection
|
9
|
+
prepend Fear::RightBiased::Interface
|
10
|
+
|
11
|
+
# @!attribute either
|
12
|
+
# @return [Fear::Either]
|
13
|
+
attr_reader :either
|
14
|
+
protected :either
|
15
|
+
|
16
|
+
# @param either [Fear::Either]
|
17
|
+
def initialize(either)
|
18
|
+
@either = either
|
19
|
+
end
|
20
|
+
|
21
|
+
# Returns +true+ if +Fear::Left+ has an element that is equal
|
22
|
+
# (as determined by +==+) to +other_value+, +false+ otherwise.
|
23
|
+
# @param [Object]
|
24
|
+
# @return [Boolean]
|
25
|
+
# @example
|
26
|
+
# Fear.left(17).left.include?(17) #=> true
|
27
|
+
# Fear.left(17).left.include?(7) #=> false
|
28
|
+
# Fear.right('undefined').left.include?(17) #=> false
|
29
|
+
#
|
30
|
+
def include?(other_value)
|
31
|
+
case either
|
32
|
+
in Fear::Left(x)
|
33
|
+
x == other_value
|
34
|
+
in Fear::Right
|
35
|
+
false
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# Returns the value from this +Fear::Left+ or evaluates the given
|
40
|
+
# default argument if this is a +Fear::Right+.
|
41
|
+
#
|
42
|
+
# @overload get_or_else(&default)
|
43
|
+
# @yieldreturn [Object]
|
44
|
+
# @return [Object]
|
45
|
+
# @example
|
46
|
+
# Fear.right(42).left.get_or_else { 24/2 } #=> 12
|
47
|
+
# Fear.left('undefined').left.get_or_else { 24/2 } #=> 'undefined'
|
48
|
+
#
|
49
|
+
# @overload get_or_else(default)
|
50
|
+
# @return [Object]
|
51
|
+
# @example
|
52
|
+
# Fear.right(42).left.get_or_else(12) #=> 12
|
53
|
+
# Fear.left('undefined').left.get_or_else(12) #=> 'undefined'
|
54
|
+
def get_or_else(*args)
|
55
|
+
case either
|
56
|
+
in Fear::Left(value)
|
57
|
+
value
|
58
|
+
in Fear::Right
|
59
|
+
args.fetch(0) { yield }
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# Performs the given block if this is a +Fear::Left+.
|
64
|
+
#
|
65
|
+
# @yieldparam [Object] value
|
66
|
+
# @yieldreturn [void]
|
67
|
+
# @return [Fear::Either] itself
|
68
|
+
# @example
|
69
|
+
# Fear.right(17).left.each do |value|
|
70
|
+
# puts value
|
71
|
+
# end #=> does nothing
|
72
|
+
#
|
73
|
+
# Fear.left('undefined').left.each do |value|
|
74
|
+
# puts value
|
75
|
+
# end #=> prints "nothing"
|
76
|
+
def each
|
77
|
+
case either
|
78
|
+
in Fear::Left(value)
|
79
|
+
yield(value)
|
80
|
+
either
|
81
|
+
in Fear::Right
|
82
|
+
either
|
83
|
+
end
|
84
|
+
end
|
85
|
+
alias apply each
|
86
|
+
|
87
|
+
# Maps the block argument through +Fear::Left+.
|
88
|
+
#
|
89
|
+
# @yieldparam [Object] value
|
90
|
+
# @yieldreturn [Fear::Either]
|
91
|
+
# @example
|
92
|
+
# Fear.left(42).left.map { _1/2 } #=> Fear.left(24)
|
93
|
+
# Fear.right(42).left.map { _1/2 } #=> Fear.right(42)
|
94
|
+
#
|
95
|
+
def map
|
96
|
+
case either
|
97
|
+
in Fear::Left(value)
|
98
|
+
Fear.left(yield(value))
|
99
|
+
in Fear::Right
|
100
|
+
either
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
# Returns the given block applied to the value from this +Fear::Left+
|
105
|
+
# or returns this if this is a +Fear::Right+.
|
106
|
+
#
|
107
|
+
# @yieldparam [Object] value
|
108
|
+
# @yieldreturn [Fear::Either]
|
109
|
+
# @return [Fear::Either]
|
110
|
+
#
|
111
|
+
# @example
|
112
|
+
# Fear.left(12).left.flat_map { Fear.left(_1 * 2) } #=> Fear.left(24)
|
113
|
+
# Fear.left(12).left.flat_map { Fear.right(_1 * 2) } #=> Fear.right(24)
|
114
|
+
# Fear.right(12).left.flat_map { Fear.left(_1 * 2) } #=> Fear.right(12)
|
115
|
+
#
|
116
|
+
def flat_map
|
117
|
+
case either
|
118
|
+
in Fear::Left(value)
|
119
|
+
yield(value)
|
120
|
+
in Fear::Right
|
121
|
+
either
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
# Returns an +Fear::Some+ containing the +Fear::Left+ value or a +Fear::None+ if
|
126
|
+
# this is a +Fear::Right+.
|
127
|
+
# @return [Fear::Option]
|
128
|
+
# @example
|
129
|
+
# Fear.left(42).left.to_option #=> Fear.some(42)
|
130
|
+
# Fear.right(42).left.to_option #=> Fear.none
|
131
|
+
#
|
132
|
+
def to_option
|
133
|
+
case either
|
134
|
+
in Fear::Left(value)
|
135
|
+
Fear.some(value)
|
136
|
+
in Fear::Right
|
137
|
+
Fear.none
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
# Returns an array containing the +Fear::Left+ value or an empty array if
|
142
|
+
# this is a +Fear::Right+.
|
143
|
+
#
|
144
|
+
# @return [Array]
|
145
|
+
# @example
|
146
|
+
# Fear.left(42).left.to_a #=> [42]
|
147
|
+
# Fear.right(42).left.to_a #=> []
|
148
|
+
#
|
149
|
+
def to_a
|
150
|
+
case either
|
151
|
+
in Fear::Left(value)
|
152
|
+
[value]
|
153
|
+
in Fear::Right
|
154
|
+
[]
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
# Returns +false+ if +Fear::Right+ or returns the result of the
|
159
|
+
# application of the given predicate to the +Fear::Light+ value.
|
160
|
+
#
|
161
|
+
# @yieldparam [Object] value
|
162
|
+
# @yieldreturn [Boolean]
|
163
|
+
# @return [Boolean]
|
164
|
+
# @example
|
165
|
+
# Fear.left(12).left.any? { |v| v > 10 } #=> true
|
166
|
+
# Fear.left(7).left.any? { |v| v > 10 } #=> false
|
167
|
+
# Fear.right(12).left.any? { |v| v > 10 } #=> false
|
168
|
+
#
|
169
|
+
def any?(&predicate)
|
170
|
+
case either
|
171
|
+
in Fear::Left(value)
|
172
|
+
predicate.(value)
|
173
|
+
in Fear::Right
|
174
|
+
false
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
# Returns +Fear::Right+ of value if the given predicate
|
179
|
+
# does not hold for the left value, otherwise, returns +Fear::Left+.
|
180
|
+
#
|
181
|
+
# @yieldparam value [Object]
|
182
|
+
# @yieldreturn [Boolean]
|
183
|
+
# @return [Fear::Either]
|
184
|
+
# @example
|
185
|
+
# Fear.left(12).left.select(&:even?) #=> Fear.left(12)
|
186
|
+
# Fear.left(7).left.select(&:even?) #=> Fear.right(7)
|
187
|
+
# Fear.right(12).left.select(&:even?) #=> Fear.right(12)
|
188
|
+
# Fear.right(7).left.select(&:even?) #=> Fear.right(7)
|
189
|
+
#
|
190
|
+
def select(&predicate)
|
191
|
+
case either
|
192
|
+
in Fear::Right
|
193
|
+
either
|
194
|
+
in Fear::Left(value) if predicate.(value)
|
195
|
+
either
|
196
|
+
in Fear::Left
|
197
|
+
either.swap
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
# Returns +Fear::None+ if this is a +Fear::Right+ or if the given predicate
|
202
|
+
# does not hold for the left value, otherwise, returns a +Fear::Left+.
|
203
|
+
#
|
204
|
+
# @yieldparam value [Object]
|
205
|
+
# @yieldreturn [Boolean]
|
206
|
+
# @return [Fear::Option<Fear::Either>]
|
207
|
+
# @example
|
208
|
+
# Fear.left(12).left.find(&:even?) #=> #<Fear::Some value=#<Fear::Left value=12>>
|
209
|
+
# Fear.left(7).left.find(&:even?) #=> #<Fear::None>
|
210
|
+
# Fear.right(12).left.find(&:even) #=> #<Fear::None>
|
211
|
+
#
|
212
|
+
def find(&predicate)
|
213
|
+
case either
|
214
|
+
in Fear::Left(value) if predicate.(value)
|
215
|
+
Fear.some(either)
|
216
|
+
in Fear::Either
|
217
|
+
Fear.none
|
218
|
+
end
|
219
|
+
end
|
220
|
+
alias detect find
|
221
|
+
|
222
|
+
# @param other [Object]
|
223
|
+
# @return [Boolean]
|
224
|
+
def ==(other)
|
225
|
+
other.is_a?(self.class) && other.either == either
|
226
|
+
end
|
227
|
+
|
228
|
+
private def left_class
|
229
|
+
Fear::Right
|
230
|
+
end
|
231
|
+
|
232
|
+
private def right_class
|
233
|
+
Fear::Left
|
234
|
+
end
|
235
|
+
end
|
236
|
+
end
|
237
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Fear
|
4
|
+
module Either
|
5
|
+
# Either pattern matcher
|
6
|
+
#
|
7
|
+
# @example
|
8
|
+
# pattern_match =
|
9
|
+
# EitherPatternMatch.new
|
10
|
+
# .right(Integer, ->(x) { x > 2 }) { |x| x * 2 }
|
11
|
+
# .right(String) { |x| x.to_i * 2 }
|
12
|
+
# .left(String) { :err }
|
13
|
+
# .else { 'error '}
|
14
|
+
#
|
15
|
+
# pattern_match.call(42) => 'NaN'
|
16
|
+
#
|
17
|
+
# @example the same matcher may be defined using block syntax
|
18
|
+
# EitherPatternMatch.new do |m|
|
19
|
+
# m.right(Integer, ->(x) { x > 2 }) { |x| x * 2 }
|
20
|
+
# m.right(String) { |x| x.to_i * 2 }
|
21
|
+
# m.left(String) { :err }
|
22
|
+
# m.else { 'error '}
|
23
|
+
# end
|
24
|
+
#
|
25
|
+
# @note it has two optimized subclasses +Fear::Left::PatternMatch+ and +Fear::Right::PatternMatch+
|
26
|
+
# @api private
|
27
|
+
class PatternMatch < Fear::PatternMatch
|
28
|
+
# Match against +Fear::Right+
|
29
|
+
#
|
30
|
+
# @param conditions [<#==>]
|
31
|
+
# @return [Fear::Either::PatternMatch]
|
32
|
+
def right(*conditions, &effect)
|
33
|
+
branch = Fear.case(Fear::Right, &:right_value).and_then(Fear.case(*conditions, &effect))
|
34
|
+
or_else(branch)
|
35
|
+
end
|
36
|
+
alias success right
|
37
|
+
|
38
|
+
# Match against +Fear::Left+
|
39
|
+
#
|
40
|
+
# @param conditions [<#==>]
|
41
|
+
# @return [Fear::Either::PatternMatch]
|
42
|
+
def left(*conditions, &effect)
|
43
|
+
branch = Fear.case(Fear::Left, &:left_value).and_then(Fear.case(*conditions, &effect))
|
44
|
+
or_else(branch)
|
45
|
+
end
|
46
|
+
alias failure left
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
data/lib/fear/either.rb
CHANGED
@@ -116,9 +116,9 @@ module Fear
|
|
116
116
|
# @yieldreturn [Boolean]
|
117
117
|
# @return [Boolean]
|
118
118
|
# @example
|
119
|
-
# Fear.right(12).any?
|
120
|
-
# Fear.right(7).any?
|
121
|
-
# Fear.left('undefined').any?
|
119
|
+
# Fear.right(12).any? { |v| v > 10 } #=> true
|
120
|
+
# Fear.right(7).any? { |v| v > 10 } #=> false
|
121
|
+
# Fear.left('undefined').any? { |v| v > 10 } #=> false
|
122
122
|
#
|
123
123
|
# -----
|
124
124
|
#
|
@@ -177,7 +177,7 @@ module Fear
|
|
177
177
|
#
|
178
178
|
# @!method swap
|
179
179
|
# If this is a +Left+, then return the left value in +Right+ or vice versa.
|
180
|
-
# @return [Either]
|
180
|
+
# @return [Fear::Either]
|
181
181
|
# @example
|
182
182
|
# Fear.left('left').swap #=> Fear.right('left')
|
183
183
|
# Fear.right('right').swap #=> Fear.left('left')
|
@@ -226,7 +226,7 @@ module Fear
|
|
226
226
|
#
|
227
227
|
# @!method match(&matcher)
|
228
228
|
# Pattern match against this +Either+
|
229
|
-
# @yield matcher [Fear::
|
229
|
+
# @yield matcher [Fear::Either::PatternMatch]
|
230
230
|
# @example
|
231
231
|
# either.match do |m|
|
232
232
|
# m.right(Integer) do |x|
|
@@ -280,6 +280,19 @@ module Fear
|
|
280
280
|
[value]
|
281
281
|
end
|
282
282
|
|
283
|
+
# Projects this +Fear::Either+ as a +Fear::Left+.
|
284
|
+
# This allows performing right-biased operation of the left
|
285
|
+
# side of the +Fear::Either+.
|
286
|
+
#
|
287
|
+
# @example
|
288
|
+
# Fear.left(42).left.map(&:succ) #=> Fear.left(43)
|
289
|
+
# Fear.right(42).left.map(&:succ) #=> Fear.left(42)
|
290
|
+
#
|
291
|
+
# @return [Fear::LeftProjection]
|
292
|
+
def left
|
293
|
+
LeftProjection.new(self)
|
294
|
+
end
|
295
|
+
|
283
296
|
class << self
|
284
297
|
# Build pattern matcher to be used later, despite off
|
285
298
|
# +Either#match+ method, id doesn't apply matcher immanently,
|
@@ -296,10 +309,10 @@ module Fear
|
|
296
309
|
# end
|
297
310
|
# matcher.call(Fear.right(42))
|
298
311
|
#
|
299
|
-
# @yieldparam [Fear::
|
312
|
+
# @yieldparam [Fear::Either::PatternMatch]
|
300
313
|
# @return [Fear::PartialFunction]
|
301
314
|
def matcher(&matcher)
|
302
|
-
|
315
|
+
Either::PatternMatch.new(&matcher)
|
303
316
|
end
|
304
317
|
end
|
305
318
|
|
@@ -331,7 +344,3 @@ module Fear
|
|
331
344
|
end
|
332
345
|
end
|
333
346
|
end
|
334
|
-
|
335
|
-
require "fear/either_pattern_match"
|
336
|
-
require "fear/left"
|
337
|
-
require "fear/right"
|
data/lib/fear/either_api.rb
CHANGED
@@ -1,10 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "fear/either"
|
4
|
-
|
5
3
|
module Fear
|
6
4
|
module EitherApi
|
7
|
-
# @param value [
|
5
|
+
# @param value [Object]
|
8
6
|
# @return [Fear::Left]
|
9
7
|
# @example
|
10
8
|
# Fear.left(42) #=> #<Fear::Left value=42>
|
@@ -13,7 +11,7 @@ module Fear
|
|
13
11
|
Fear::Left.new(value)
|
14
12
|
end
|
15
13
|
|
16
|
-
# @param value [
|
14
|
+
# @param value [Object]
|
17
15
|
# @return [Fear::Right]
|
18
16
|
# @example
|
19
17
|
# Fear.right(42) #=> #<Fear::Right value=42>
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Fear
|
4
|
-
# Use singleton version of EmptyPartialFunction -- PartialFunction::
|
4
|
+
# Use singleton version of EmptyPartialFunction -- PartialFunction::Empty
|
5
5
|
# @api private
|
6
6
|
class EmptyPartialFunction
|
7
7
|
include PartialFunction
|
data/lib/fear/failure.rb
CHANGED
data/lib/fear/for_api.rb
CHANGED
data/lib/fear/future.rb
CHANGED
@@ -170,7 +170,7 @@ module Fear
|
|
170
170
|
#
|
171
171
|
# If the future has already been completed,
|
172
172
|
# this will either be applied immediately or be scheduled asynchronously.
|
173
|
-
# @yieldparam [Fear::
|
173
|
+
# @yieldparam [Fear::Try::PatternMatch]
|
174
174
|
# @return [self]
|
175
175
|
#
|
176
176
|
# @example
|
data/lib/fear/future_api.rb
CHANGED
@@ -6,11 +6,6 @@ rescue LoadError
|
|
6
6
|
puts "You must add 'concurrent-ruby' to your Gemfile in order to use Fear::Future"
|
7
7
|
end
|
8
8
|
|
9
|
-
require "fear/awaitable"
|
10
|
-
require "fear/await"
|
11
|
-
require "fear/future"
|
12
|
-
require "fear/promise"
|
13
|
-
|
14
9
|
module Fear
|
15
10
|
# rubocop: disable Layout/LineLength
|
16
11
|
module FutureApi
|