fear 1.0.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 +39 -0
- data/.github/workflows/spec.yml +42 -0
- data/.rubocop.yml +4 -60
- data/.simplecov +17 -0
- data/CHANGELOG.md +29 -1
- data/Gemfile +5 -5
- data/Gemfile.lock +86 -50
- data/README.md +240 -209
- data/Rakefile +72 -65
- data/examples/pattern_extracting.rb +10 -8
- data/examples/pattern_matching_binary_tree_set.rb +7 -2
- data/examples/pattern_matching_number_in_words.rb +48 -42
- data/fear.gemspec +33 -34
- data/lib/dry/types/fear/option.rb +125 -0
- data/lib/dry/types/fear.rb +8 -0
- data/lib/fear/await.rb +33 -0
- data/lib/fear/awaitable.rb +28 -0
- data/lib/fear/either.rb +15 -4
- data/lib/fear/either_api.rb +4 -0
- data/lib/fear/either_pattern_match.rb +9 -5
- data/lib/fear/empty_partial_function.rb +3 -1
- data/lib/fear/failure.rb +7 -7
- data/lib/fear/failure_pattern_match.rb +4 -0
- data/lib/fear/for.rb +4 -2
- data/lib/fear/for_api.rb +5 -1
- data/lib/fear/future.rb +157 -82
- data/lib/fear/future_api.rb +17 -4
- data/lib/fear/left.rb +3 -9
- data/lib/fear/left_pattern_match.rb +2 -0
- data/lib/fear/none.rb +28 -10
- data/lib/fear/none_pattern_match.rb +2 -0
- data/lib/fear/option.rb +30 -2
- data/lib/fear/option_api.rb +4 -0
- data/lib/fear/option_pattern_match.rb +8 -3
- data/lib/fear/partial_function/and_then.rb +4 -2
- data/lib/fear/partial_function/any.rb +2 -0
- data/lib/fear/partial_function/combined.rb +3 -1
- data/lib/fear/partial_function/empty.rb +6 -0
- data/lib/fear/partial_function/guard/and.rb +2 -0
- data/lib/fear/partial_function/guard/and3.rb +2 -0
- data/lib/fear/partial_function/guard/or.rb +2 -0
- data/lib/fear/partial_function/guard.rb +8 -6
- data/lib/fear/partial_function/lifted.rb +2 -0
- data/lib/fear/partial_function/or_else.rb +5 -1
- data/lib/fear/partial_function.rb +18 -9
- data/lib/fear/partial_function_class.rb +3 -1
- data/lib/fear/pattern_match.rb +3 -11
- data/lib/fear/pattern_matching_api.rb +6 -28
- data/lib/fear/promise.rb +7 -5
- data/lib/fear/right.rb +3 -9
- data/lib/fear/right_biased.rb +5 -3
- data/lib/fear/right_pattern_match.rb +4 -0
- data/lib/fear/some.rb +35 -8
- data/lib/fear/some_pattern_match.rb +2 -0
- data/lib/fear/struct.rb +237 -0
- data/lib/fear/success.rb +7 -8
- data/lib/fear/success_pattern_match.rb +4 -0
- data/lib/fear/try.rb +8 -2
- data/lib/fear/try_api.rb +4 -0
- data/lib/fear/try_pattern_match.rb +9 -5
- data/lib/fear/unit.rb +6 -2
- data/lib/fear/utils.rb +14 -2
- data/lib/fear/version.rb +4 -1
- data/lib/fear.rb +26 -44
- data/spec/dry/types/fear/option/constrained_spec.rb +22 -0
- data/spec/dry/types/fear/option/core_spec.rb +77 -0
- data/spec/dry/types/fear/option/default_spec.rb +21 -0
- data/spec/dry/types/fear/option/hash_spec.rb +58 -0
- data/spec/dry/types/fear/option/option_spec.rb +97 -0
- data/spec/fear/awaitable_spec.rb +19 -0
- data/spec/fear/done_spec.rb +7 -5
- data/spec/fear/either/mixin_spec.rb +4 -2
- data/spec/fear/either_pattern_match_spec.rb +10 -8
- data/spec/fear/either_pattern_matching_spec.rb +28 -0
- data/spec/fear/either_spec.rb +26 -0
- data/spec/fear/failure_spec.rb +57 -70
- data/spec/fear/for/mixin_spec.rb +15 -0
- data/spec/fear/for_spec.rb +19 -17
- data/spec/fear/future_spec.rb +477 -237
- data/spec/fear/guard_spec.rb +136 -24
- data/spec/fear/left_spec.rb +57 -70
- data/spec/fear/none_spec.rb +39 -43
- data/spec/fear/option/mixin_spec.rb +9 -7
- data/spec/fear/option_pattern_match_spec.rb +10 -8
- data/spec/fear/option_pattern_matching_spec.rb +34 -0
- data/spec/fear/option_spec.rb +142 -0
- data/spec/fear/partial_function/any_spec.rb +25 -0
- data/spec/fear/partial_function/empty_spec.rb +12 -10
- data/spec/fear/partial_function_and_then_spec.rb +39 -37
- data/spec/fear/partial_function_composition_spec.rb +46 -44
- data/spec/fear/partial_function_or_else_spec.rb +92 -90
- data/spec/fear/partial_function_spec.rb +91 -61
- data/spec/fear/pattern_match_spec.rb +19 -51
- data/spec/fear/pattern_matching_api_spec.rb +31 -0
- data/spec/fear/promise_spec.rb +23 -23
- data/spec/fear/right_biased/left.rb +28 -26
- data/spec/fear/right_biased/right.rb +51 -49
- data/spec/fear/right_spec.rb +48 -68
- data/spec/fear/some_spec.rb +30 -40
- data/spec/fear/success_spec.rb +40 -60
- data/spec/fear/try/mixin_spec.rb +19 -3
- data/spec/fear/try_api_spec.rb +23 -0
- data/spec/fear/try_pattern_match_spec.rb +10 -8
- data/spec/fear/try_pattern_matching_spec.rb +34 -0
- data/spec/fear/utils_spec.rb +16 -14
- data/spec/spec_helper.rb +13 -7
- data/spec/struct_pattern_matching_spec.rb +36 -0
- data/spec/struct_spec.rb +194 -0
- data/spec/support/dry_types.rb +6 -0
- metadata +128 -87
- data/.travis.yml +0 -13
- data/lib/fear/extractor/anonymous_array_splat_matcher.rb +0 -8
- data/lib/fear/extractor/any_matcher.rb +0 -15
- data/lib/fear/extractor/array_head_matcher.rb +0 -34
- data/lib/fear/extractor/array_matcher.rb +0 -38
- data/lib/fear/extractor/array_splat_matcher.rb +0 -14
- data/lib/fear/extractor/empty_list_matcher.rb +0 -18
- data/lib/fear/extractor/extractor_matcher.rb +0 -42
- data/lib/fear/extractor/grammar.rb +0 -201
- data/lib/fear/extractor/grammar.treetop +0 -129
- data/lib/fear/extractor/identifier_matcher.rb +0 -16
- data/lib/fear/extractor/matcher/and.rb +0 -36
- data/lib/fear/extractor/matcher.rb +0 -54
- data/lib/fear/extractor/named_array_splat_matcher.rb +0 -15
- data/lib/fear/extractor/pattern.rb +0 -55
- data/lib/fear/extractor/typed_identifier_matcher.rb +0 -24
- data/lib/fear/extractor/value_matcher.rb +0 -17
- data/lib/fear/extractor.rb +0 -108
- data/lib/fear/extractor_api.rb +0 -33
- data/spec/fear/extractor/array_matcher_spec.rb +0 -228
- data/spec/fear/extractor/extractor_matcher_spec.rb +0 -151
- data/spec/fear/extractor/grammar_array_spec.rb +0 -23
- data/spec/fear/extractor/identified_matcher_spec.rb +0 -47
- data/spec/fear/extractor/identifier_matcher_spec.rb +0 -66
- data/spec/fear/extractor/pattern_spec.rb +0 -32
- data/spec/fear/extractor/typed_identifier_matcher_spec.rb +0 -62
- data/spec/fear/extractor/value_matcher_number_spec.rb +0 -77
- data/spec/fear/extractor/value_matcher_string_spec.rb +0 -86
- data/spec/fear/extractor/value_matcher_symbol_spec.rb +0 -69
- data/spec/fear/extractor_api_spec.rb +0 -113
- data/spec/fear/extractor_spec.rb +0 -59
@@ -1,273 +1,275 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.describe Fear::PartialFunction, "#or_else" do
|
2
4
|
subject(:first_or_else_second) { first.or_else(second) }
|
3
5
|
|
4
6
|
let(:first) { Fear.case(->(x) { x.even? }) { |x| "first: #{x}" } }
|
5
7
|
let(:second) { Fear.case(->(x) { x % 3 == 0 }) { |x| "second: #{x}" } }
|
6
8
|
|
7
|
-
describe
|
8
|
-
context
|
9
|
+
describe "#defined_at?" do
|
10
|
+
context "first defined, second not" do
|
9
11
|
subject { first_or_else_second.defined_at?(4) }
|
10
12
|
|
11
13
|
it { is_expected.to eq(true) }
|
12
14
|
end
|
13
15
|
|
14
|
-
context
|
16
|
+
context "first not defined, second defined" do
|
15
17
|
subject { first_or_else_second.defined_at?(9) }
|
16
18
|
|
17
19
|
it { is_expected.to eq(true) }
|
18
20
|
end
|
19
21
|
|
20
|
-
context
|
22
|
+
context "first not defined, second not defined" do
|
21
23
|
subject { first_or_else_second.defined_at?(5) }
|
22
24
|
|
23
25
|
it { is_expected.to eq(false) }
|
24
26
|
end
|
25
27
|
|
26
|
-
context
|
28
|
+
context "first and second defined" do
|
27
29
|
subject { first_or_else_second.defined_at?(6) }
|
28
30
|
|
29
31
|
it { is_expected.to eq(true) }
|
30
32
|
end
|
31
33
|
end
|
32
34
|
|
33
|
-
describe
|
34
|
-
context
|
35
|
-
subject { first_or_else_second.
|
35
|
+
describe "#call" do
|
36
|
+
context "first defined, second not" do
|
37
|
+
subject { first_or_else_second.(4) }
|
36
38
|
|
37
|
-
it { is_expected.to eq(
|
39
|
+
it { is_expected.to eq("first: 4") }
|
38
40
|
end
|
39
41
|
|
40
|
-
context
|
41
|
-
subject { first_or_else_second.
|
42
|
+
context "first not defined, second defined" do
|
43
|
+
subject { first_or_else_second.(9) }
|
42
44
|
|
43
|
-
it { is_expected.to eq(
|
45
|
+
it { is_expected.to eq("second: 9") }
|
44
46
|
end
|
45
47
|
|
46
|
-
context
|
47
|
-
subject { -> { first_or_else_second.
|
48
|
+
context "first not defined, second not defined" do
|
49
|
+
subject { -> { first_or_else_second.(5) } }
|
48
50
|
|
49
|
-
it { is_expected.to raise_error(Fear::MatchError,
|
51
|
+
it { is_expected.to raise_error(Fear::MatchError, "partial function not defined at: 5") }
|
50
52
|
end
|
51
53
|
|
52
|
-
context
|
53
|
-
subject { first_or_else_second.
|
54
|
+
context "first and second defined" do
|
55
|
+
subject { first_or_else_second.(6) }
|
54
56
|
|
55
|
-
it { is_expected.to eq(
|
57
|
+
it { is_expected.to eq("first: 6") }
|
56
58
|
end
|
57
59
|
end
|
58
60
|
|
59
|
-
describe
|
61
|
+
describe "#call_or_else" do
|
60
62
|
let(:fallback) { ->(x) { "fallback: #{x}" } }
|
61
63
|
|
62
|
-
context
|
64
|
+
context "first defined, second not" do
|
63
65
|
subject { first_or_else_second.call_or_else(4, &fallback) }
|
64
66
|
|
65
|
-
it { is_expected.to eq(
|
67
|
+
it { is_expected.to eq("first: 4") }
|
66
68
|
end
|
67
69
|
|
68
|
-
context
|
70
|
+
context "first not defined, second defined" do
|
69
71
|
subject { first_or_else_second.call_or_else(9, &fallback) }
|
70
72
|
|
71
|
-
it { is_expected.to eq(
|
73
|
+
it { is_expected.to eq("second: 9") }
|
72
74
|
end
|
73
75
|
|
74
|
-
context
|
76
|
+
context "first not defined, second not defined" do
|
75
77
|
subject { first_or_else_second.call_or_else(5, &fallback) }
|
76
78
|
|
77
|
-
it { is_expected.to eq(
|
79
|
+
it { is_expected.to eq("fallback: 5") }
|
78
80
|
end
|
79
81
|
|
80
|
-
context
|
82
|
+
context "first and second defined" do
|
81
83
|
subject { first_or_else_second.call_or_else(6, &fallback) }
|
82
84
|
|
83
|
-
it { is_expected.to eq(
|
85
|
+
it { is_expected.to eq("first: 6") }
|
84
86
|
end
|
85
87
|
end
|
86
88
|
|
87
|
-
describe
|
89
|
+
describe "#or_else" do
|
88
90
|
let(:first_or_else_second_or_else_third) { first_or_else_second.or_else(third) }
|
89
91
|
let(:third) { Fear.case(->(x) { x % 7 == 0 }) { |x| "third: #{x}" } }
|
90
92
|
|
91
|
-
describe
|
92
|
-
context
|
93
|
+
describe "#defined_at?" do
|
94
|
+
context "first defined, second not" do
|
93
95
|
subject { first_or_else_second_or_else_third.defined_at?(4) }
|
94
96
|
|
95
97
|
it { is_expected.to eq(true) }
|
96
98
|
end
|
97
99
|
|
98
|
-
context
|
100
|
+
context "first not defined, second defined" do
|
99
101
|
subject { first_or_else_second_or_else_third.defined_at?(9) }
|
100
102
|
|
101
103
|
it { is_expected.to eq(true) }
|
102
104
|
end
|
103
105
|
|
104
|
-
context
|
106
|
+
context "first not defined, second not defined, third defined" do
|
105
107
|
subject { first_or_else_second_or_else_third.defined_at?(7) }
|
106
108
|
|
107
109
|
it { is_expected.to eq(true) }
|
108
110
|
end
|
109
111
|
|
110
|
-
context
|
112
|
+
context "first not defined, second not defined, third not defined" do
|
111
113
|
subject { first_or_else_second_or_else_third.defined_at?(1) }
|
112
114
|
|
113
115
|
it { is_expected.to eq(false) }
|
114
116
|
end
|
115
117
|
|
116
|
-
context
|
118
|
+
context "first, second and third defined" do
|
117
119
|
subject { first_or_else_second.defined_at?(42) }
|
118
120
|
|
119
121
|
it { is_expected.to eq(true) }
|
120
122
|
end
|
121
123
|
end
|
122
124
|
|
123
|
-
describe
|
124
|
-
context
|
125
|
-
subject { first_or_else_second_or_else_third.
|
125
|
+
describe "#call" do
|
126
|
+
context "first defined, second not" do
|
127
|
+
subject { first_or_else_second_or_else_third.(4) }
|
126
128
|
|
127
|
-
it { is_expected.to eq(
|
129
|
+
it { is_expected.to eq("first: 4") }
|
128
130
|
end
|
129
131
|
|
130
|
-
context
|
131
|
-
subject { first_or_else_second_or_else_third.
|
132
|
+
context "first not defined, second defined" do
|
133
|
+
subject { first_or_else_second_or_else_third.(9) }
|
132
134
|
|
133
|
-
it { is_expected.to eq(
|
135
|
+
it { is_expected.to eq("second: 9") }
|
134
136
|
end
|
135
137
|
|
136
|
-
context
|
137
|
-
subject { first_or_else_second_or_else_third.
|
138
|
+
context "first not defined, second not defined, third defined" do
|
139
|
+
subject { first_or_else_second_or_else_third.(7) }
|
138
140
|
|
139
|
-
it { is_expected.to eq(
|
141
|
+
it { is_expected.to eq("third: 7") }
|
140
142
|
end
|
141
143
|
|
142
|
-
context
|
143
|
-
subject { -> { first_or_else_second_or_else_third.
|
144
|
+
context "first not defined, second not defined, third not defined" do
|
145
|
+
subject { -> { first_or_else_second_or_else_third.(1) } }
|
144
146
|
|
145
|
-
it { is_expected.to raise_error(Fear::MatchError,
|
147
|
+
it { is_expected.to raise_error(Fear::MatchError, "partial function not defined at: 1") }
|
146
148
|
end
|
147
149
|
|
148
|
-
context
|
149
|
-
subject { first_or_else_second.
|
150
|
+
context "first, second and third defined" do
|
151
|
+
subject { first_or_else_second.(42) }
|
150
152
|
|
151
|
-
it { is_expected.to eq(
|
153
|
+
it { is_expected.to eq("first: 42") }
|
152
154
|
end
|
153
155
|
end
|
154
156
|
|
155
|
-
describe
|
157
|
+
describe "#call_or_else" do
|
156
158
|
let(:fallback) { ->(x) { "fallback: #{x}" } }
|
157
159
|
|
158
|
-
context
|
160
|
+
context "first defined, second not" do
|
159
161
|
subject { first_or_else_second_or_else_third.call_or_else(4, &fallback) }
|
160
162
|
|
161
|
-
it { is_expected.to eq(
|
163
|
+
it { is_expected.to eq("first: 4") }
|
162
164
|
end
|
163
165
|
|
164
|
-
context
|
166
|
+
context "first not defined, second defined" do
|
165
167
|
subject { first_or_else_second_or_else_third.call_or_else(9, &fallback) }
|
166
168
|
|
167
|
-
it { is_expected.to eq(
|
169
|
+
it { is_expected.to eq("second: 9") }
|
168
170
|
end
|
169
171
|
|
170
|
-
context
|
172
|
+
context "first not defined, second not defined, third defined" do
|
171
173
|
subject { first_or_else_second_or_else_third.call_or_else(7, &fallback) }
|
172
174
|
|
173
|
-
it { is_expected.to eq(
|
175
|
+
it { is_expected.to eq("third: 7") }
|
174
176
|
end
|
175
177
|
|
176
|
-
context
|
178
|
+
context "first not defined, second not defined, third not defined" do
|
177
179
|
subject { first_or_else_second_or_else_third.call_or_else(1, &fallback) }
|
178
180
|
|
179
|
-
it { is_expected.to eq(
|
181
|
+
it { is_expected.to eq("fallback: 1") }
|
180
182
|
end
|
181
183
|
|
182
|
-
context
|
184
|
+
context "first, second and third defined" do
|
183
185
|
subject { first_or_else_second_or_else_third.call_or_else(42, &fallback) }
|
184
186
|
|
185
|
-
it { is_expected.to eq(
|
187
|
+
it { is_expected.to eq("first: 42") }
|
186
188
|
end
|
187
189
|
end
|
188
190
|
end
|
189
191
|
|
190
|
-
describe
|
192
|
+
describe "#and_then" do
|
191
193
|
let(:first_or_else_second_and_then_function) { first_or_else_second.and_then(&function) }
|
192
194
|
let(:function) { ->(x) { "f: #{x}" } }
|
193
195
|
|
194
|
-
describe
|
195
|
-
context
|
196
|
+
describe "#defined_at?" do
|
197
|
+
context "first defined, second not" do
|
196
198
|
subject { first_or_else_second_and_then_function.defined_at?(2) }
|
197
199
|
|
198
200
|
it { is_expected.to eq(true) }
|
199
201
|
end
|
200
202
|
|
201
|
-
context
|
203
|
+
context "first not defined, second defined" do
|
202
204
|
subject { first_or_else_second_and_then_function.defined_at?(3) }
|
203
205
|
|
204
206
|
it { is_expected.to eq(true) }
|
205
207
|
end
|
206
208
|
|
207
|
-
context
|
209
|
+
context "first not defined, second not defined" do
|
208
210
|
subject { first_or_else_second_and_then_function.defined_at?(5) }
|
209
211
|
|
210
212
|
it { is_expected.to eq(false) }
|
211
213
|
end
|
212
214
|
|
213
|
-
context
|
215
|
+
context "first defined, second defined" do
|
214
216
|
subject { first_or_else_second_and_then_function.defined_at?(6) }
|
215
217
|
|
216
218
|
it { is_expected.to eq(true) }
|
217
219
|
end
|
218
220
|
end
|
219
221
|
|
220
|
-
describe
|
221
|
-
context
|
222
|
-
subject { first_or_else_second_and_then_function.
|
222
|
+
describe "#call" do
|
223
|
+
context "first defined, second not" do
|
224
|
+
subject { first_or_else_second_and_then_function.(2) }
|
223
225
|
|
224
|
-
it { is_expected.to eq(
|
226
|
+
it { is_expected.to eq("f: first: 2") }
|
225
227
|
end
|
226
228
|
|
227
|
-
context
|
228
|
-
subject { first_or_else_second_and_then_function.
|
229
|
+
context "first not defined, second defined" do
|
230
|
+
subject { first_or_else_second_and_then_function.(3) }
|
229
231
|
|
230
|
-
it { is_expected.to eq(
|
232
|
+
it { is_expected.to eq("f: second: 3") }
|
231
233
|
end
|
232
234
|
|
233
|
-
context
|
234
|
-
subject { -> { first_or_else_second_and_then_function.
|
235
|
+
context "first not defined, second not defined" do
|
236
|
+
subject { -> { first_or_else_second_and_then_function.(5) } }
|
235
237
|
|
236
|
-
it { is_expected.to raise_error(Fear::MatchError,
|
238
|
+
it { is_expected.to raise_error(Fear::MatchError, "partial function not defined at: 5") }
|
237
239
|
end
|
238
240
|
|
239
|
-
context
|
240
|
-
subject { first_or_else_second_and_then_function.
|
241
|
+
context "first defined, second defined" do
|
242
|
+
subject { first_or_else_second_and_then_function.(6) }
|
241
243
|
|
242
|
-
it { is_expected.to eq(
|
244
|
+
it { is_expected.to eq("f: first: 6") }
|
243
245
|
end
|
244
246
|
end
|
245
247
|
|
246
|
-
describe
|
248
|
+
describe "#call_or_else" do
|
247
249
|
let(:fallback) { ->(x) { "fallback: #{x}" } }
|
248
250
|
|
249
|
-
context
|
251
|
+
context "first defined, second not" do
|
250
252
|
subject { first_or_else_second_and_then_function.call_or_else(2, &fallback) }
|
251
253
|
|
252
|
-
it { is_expected.to eq(
|
254
|
+
it { is_expected.to eq("f: first: 2") }
|
253
255
|
end
|
254
256
|
|
255
|
-
context
|
257
|
+
context "first not defined, second defined" do
|
256
258
|
subject { first_or_else_second_and_then_function.call_or_else(3, &fallback) }
|
257
259
|
|
258
|
-
it { is_expected.to eq(
|
260
|
+
it { is_expected.to eq("f: second: 3") }
|
259
261
|
end
|
260
262
|
|
261
|
-
context
|
263
|
+
context "first not defined, second not defined" do
|
262
264
|
subject { first_or_else_second_and_then_function.call_or_else(5, &fallback) }
|
263
265
|
|
264
|
-
it { is_expected.to eq(
|
266
|
+
it { is_expected.to eq("fallback: 5") }
|
265
267
|
end
|
266
268
|
|
267
|
-
context
|
269
|
+
context "first defined, second defined" do
|
268
270
|
subject { first_or_else_second_and_then_function.call_or_else(6, &fallback) }
|
269
271
|
|
270
|
-
it { is_expected.to eq(
|
272
|
+
it { is_expected.to eq("f: first: 6") }
|
271
273
|
end
|
272
274
|
end
|
273
275
|
end
|
@@ -1,36 +1,26 @@
|
|
1
|
-
|
2
|
-
describe 'Fear.case()' do
|
3
|
-
context 'condition is extractor' do
|
4
|
-
subject do
|
5
|
-
Fear.xcase('[1, [2, second_of_second, *], 3, *rest]') do |second_of_second:, rest:|
|
6
|
-
[second_of_second, rest]
|
7
|
-
end
|
8
|
-
end
|
9
|
-
|
10
|
-
it { is_expected.to be_defined_at([1, [2, 2, 3, 4], 3, 6, 7]) }
|
11
|
-
it { is_expected.not_to be_defined_at([1, [1, 3, 3, 4], 3, 6, 7]) }
|
12
|
-
it { is_expected.not_to be_defined_at([1, [1, 2, 3, 4], 4, 6, 7]) }
|
13
|
-
end
|
1
|
+
# frozen_string_literal: true
|
14
2
|
|
15
|
-
|
3
|
+
RSpec.describe Fear::PartialFunction do
|
4
|
+
describe "Fear.case()" do
|
5
|
+
context "condition as symbol" do
|
16
6
|
subject { Fear.case(:even?) { |x| x } }
|
17
7
|
|
18
|
-
it
|
8
|
+
it "matches against the same symbol" do
|
19
9
|
is_expected.to be_defined_at(:even?)
|
20
10
|
is_expected.not_to be_defined_at(3)
|
21
11
|
end
|
22
12
|
end
|
23
13
|
|
24
|
-
context
|
14
|
+
context "condition as Class" do
|
25
15
|
subject { Fear.case(Integer) { |x| x } }
|
26
16
|
|
27
17
|
it do
|
28
18
|
is_expected.to be_defined_at(4)
|
29
|
-
is_expected.not_to be_defined_at(
|
19
|
+
is_expected.not_to be_defined_at("3")
|
30
20
|
end
|
31
21
|
end
|
32
22
|
|
33
|
-
context
|
23
|
+
context "condition as Proc" do
|
34
24
|
subject { Fear.case(->(x) { x.even? }) { |x| x } }
|
35
25
|
|
36
26
|
it do
|
@@ -39,19 +29,19 @@ RSpec.describe Fear::PartialFunction do
|
|
39
29
|
end
|
40
30
|
end
|
41
31
|
|
42
|
-
context
|
32
|
+
context "multiple condition" do
|
43
33
|
subject { Fear.case(Integer, :even?.to_proc, ->(x) { x % 3 == 0 }) { |x| x } }
|
44
34
|
|
45
35
|
it do
|
46
36
|
is_expected.to be_defined_at(12)
|
47
37
|
is_expected.not_to be_defined_at(12.0)
|
48
|
-
is_expected.not_to be_defined_at(
|
38
|
+
is_expected.not_to be_defined_at("3")
|
49
39
|
is_expected.not_to be_defined_at(3)
|
50
40
|
is_expected.not_to be_defined_at(4)
|
51
41
|
end
|
52
42
|
end
|
53
43
|
|
54
|
-
context
|
44
|
+
context "multiple condition 2" do
|
55
45
|
subject { Fear.case(Integer, 4) { |x| x } }
|
56
46
|
|
57
47
|
it do
|
@@ -61,127 +51,167 @@ RSpec.describe Fear::PartialFunction do
|
|
61
51
|
end
|
62
52
|
end
|
63
53
|
|
64
|
-
describe
|
54
|
+
describe ".or" do
|
55
|
+
subject { described_class.or(guard_1, guard_2, &:itself) }
|
56
|
+
|
57
|
+
let(:guard_1) { ->(x) { x == 42 } }
|
58
|
+
let(:guard_2) { ->(x) { x == 21 } }
|
59
|
+
|
60
|
+
it { is_expected.to be_defined_at(42) }
|
61
|
+
it { is_expected.to be_defined_at(21) }
|
62
|
+
it { is_expected.not_to be_defined_at(20) }
|
63
|
+
end
|
64
|
+
|
65
|
+
describe ".and" do
|
66
|
+
subject { described_class.and(guard_1, guard_2, &:itself) }
|
67
|
+
|
68
|
+
let(:guard_1) { ->(x) { x % 5 == 0 } }
|
69
|
+
let(:guard_2) { ->(x) { x % 2 == 0 } }
|
70
|
+
|
71
|
+
it { is_expected.to be_defined_at(10) }
|
72
|
+
it { is_expected.not_to be_defined_at(5) }
|
73
|
+
it { is_expected.not_to be_defined_at(2) }
|
74
|
+
it { is_expected.not_to be_defined_at(3) }
|
75
|
+
end
|
76
|
+
|
77
|
+
describe "#lift" do
|
65
78
|
let(:lifted) { partial_function.lift }
|
66
79
|
|
67
80
|
let(:partial_function) { Fear.case(->(v) { v != 0 }) { |x| 4 / x } }
|
68
81
|
|
69
|
-
context
|
70
|
-
subject { lifted.
|
82
|
+
context "defined" do
|
83
|
+
subject { lifted.(2) }
|
71
84
|
|
72
85
|
it { is_expected.to eq(Fear::Some.new(2)) }
|
73
86
|
end
|
74
87
|
|
75
|
-
context
|
76
|
-
subject { lifted.
|
88
|
+
context "not defined" do
|
89
|
+
subject { lifted.(0) }
|
77
90
|
|
78
91
|
it { is_expected.to eq(Fear::None) }
|
79
92
|
end
|
80
93
|
end
|
81
94
|
|
82
|
-
describe
|
95
|
+
describe "#defined_at?" do
|
83
96
|
let(:partial_function) { Fear.case(->(v) { v == 42 }) {} }
|
84
97
|
|
85
|
-
it
|
98
|
+
it "defined at" do
|
86
99
|
expect(partial_function.defined_at?(42)).to eq(true)
|
87
100
|
end
|
88
101
|
|
89
|
-
it
|
102
|
+
it "not defined at" do
|
90
103
|
expect(partial_function.defined_at?(24)).to eq(false)
|
91
104
|
end
|
92
105
|
end
|
93
106
|
|
94
|
-
describe
|
107
|
+
describe "#call" do
|
95
108
|
let(:partial_function) { Fear.case(->(v) { v != 0 }) { |x| 4 / x } }
|
96
109
|
|
97
|
-
context
|
98
|
-
subject { partial_function.
|
110
|
+
context "defined" do
|
111
|
+
subject { partial_function.(2) }
|
99
112
|
|
100
113
|
it { is_expected.to eq(2) }
|
101
114
|
end
|
102
115
|
|
103
|
-
context
|
104
|
-
subject { -> { partial_function.
|
116
|
+
context "not defined" do
|
117
|
+
subject { -> { partial_function.(0) } }
|
105
118
|
|
106
|
-
it { is_expected.to raise_error(Fear::MatchError,
|
107
|
-
end
|
108
|
-
|
109
|
-
context 'defined and condition is extractor' do
|
110
|
-
subject { partial_function.call([1, 2, 3, 4, 5]) }
|
111
|
-
|
112
|
-
let(:partial_function) do
|
113
|
-
Fear.xcase('[1, second, 3, *rest]') { |second:, rest:| [second, rest] }
|
114
|
-
end
|
115
|
-
|
116
|
-
it { is_expected.to eq([2, [4, 5]]) }
|
119
|
+
it { is_expected.to raise_error(Fear::MatchError, "partial function not defined at: 0") }
|
117
120
|
end
|
118
121
|
end
|
119
122
|
|
120
|
-
describe
|
123
|
+
describe "#to_proc", "#call" do
|
121
124
|
let(:partial_function) { Fear.case(->(v) { v != 0 }) { |x| 4 / x }.to_proc }
|
122
125
|
|
123
|
-
context
|
124
|
-
subject { partial_function.
|
126
|
+
context "defined" do
|
127
|
+
subject { partial_function.(2) }
|
125
128
|
|
126
129
|
it { is_expected.to eq(2) }
|
127
130
|
end
|
128
131
|
|
129
|
-
context
|
130
|
-
subject { -> { partial_function.
|
132
|
+
context "not defined" do
|
133
|
+
subject { -> { partial_function.(0) } }
|
131
134
|
|
132
|
-
it { is_expected.to raise_error(Fear::MatchError,
|
135
|
+
it { is_expected.to raise_error(Fear::MatchError, "partial function not defined at: 0") }
|
133
136
|
end
|
134
137
|
end
|
135
138
|
|
136
|
-
describe
|
139
|
+
describe "#call_or_else" do
|
137
140
|
let(:default) { ->(x) { "division by #{x} impossible" } }
|
138
141
|
let(:partial_function) { Fear.case(->(x) { x != 0 }) { |x| 4 / x } }
|
139
142
|
|
140
|
-
context
|
143
|
+
context "defined" do
|
141
144
|
subject { partial_function.call_or_else(2, &default) }
|
142
145
|
|
143
146
|
it { is_expected.to eq(2) }
|
144
147
|
end
|
145
148
|
|
146
|
-
context
|
149
|
+
context "not defined" do
|
147
150
|
subject { partial_function.call_or_else(0, &default) }
|
148
151
|
|
149
|
-
it { is_expected.to eq(
|
152
|
+
it { is_expected.to eq("division by 0 impossible") }
|
150
153
|
end
|
151
154
|
end
|
152
155
|
|
153
|
-
describe
|
156
|
+
describe "#and_then" do
|
154
157
|
let(:partial_function) { Fear.case(->(v) { v == 42 }) {} }
|
155
158
|
let(:and_then) { ->(x) { x } }
|
156
159
|
|
157
|
-
context
|
160
|
+
context "block given, arguments not given" do
|
158
161
|
subject { -> { partial_function.and_then(&and_then) } }
|
159
162
|
|
160
163
|
it { is_expected.not_to raise_error }
|
161
164
|
end
|
162
165
|
|
163
|
-
context
|
166
|
+
context "block given, argument given" do
|
164
167
|
subject { -> { partial_function.and_then(and_then, &and_then) } }
|
165
168
|
|
166
169
|
it { is_expected.to raise_error(ArgumentError) }
|
167
170
|
end
|
168
171
|
|
169
|
-
context
|
172
|
+
context "block given, arguments given" do
|
170
173
|
subject { -> { partial_function.and_then(and_then, 42, &and_then) } }
|
171
174
|
|
172
175
|
it { is_expected.to raise_error(ArgumentError) }
|
173
176
|
end
|
174
177
|
|
175
|
-
context
|
178
|
+
context "block not given, arguments not given" do
|
176
179
|
subject { -> { partial_function.and_then } }
|
177
180
|
|
178
181
|
it { is_expected.to raise_error(ArgumentError) }
|
179
182
|
end
|
180
183
|
|
181
|
-
context
|
184
|
+
context "block net given, arguments given" do
|
182
185
|
subject { -> { partial_function.and_then(and_then) } }
|
183
186
|
|
184
187
|
it { is_expected.not_to raise_error }
|
185
188
|
end
|
186
189
|
end
|
190
|
+
|
191
|
+
shared_examples "#or_else" do |method_name|
|
192
|
+
subject { is_even.__send__(method_name, is_odd).(value) }
|
193
|
+
|
194
|
+
let(:is_even) { Fear.case(:even?.to_proc) { |x| "#{x} is even" } }
|
195
|
+
let(:is_odd) { Fear.case(:odd?.to_proc) { |x| "#{x} is odd" } }
|
196
|
+
|
197
|
+
context "when left side is defined" do
|
198
|
+
let(:value) { 42 }
|
199
|
+
|
200
|
+
it { is_expected.to eq("42 is even") }
|
201
|
+
end
|
202
|
+
|
203
|
+
context "when left side is not defined" do
|
204
|
+
let(:value) { 21 }
|
205
|
+
|
206
|
+
it { is_expected.to eq("21 is odd") }
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
describe "#or_else" do
|
211
|
+
include_examples "#or_else", :or_else
|
212
|
+
end
|
213
|
+
|
214
|
+
describe "#|" do
|
215
|
+
include_examples "#or_else", :|
|
216
|
+
end
|
187
217
|
end
|