fear 0.9.0 → 1.2.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 (155) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/rubocop.yml +39 -0
  3. data/.github/workflows/spec.yml +42 -0
  4. data/.gitignore +0 -1
  5. data/.rubocop.yml +4 -12
  6. data/.simplecov +17 -0
  7. data/CHANGELOG.md +40 -0
  8. data/Gemfile +5 -2
  9. data/Gemfile.lock +130 -0
  10. data/LICENSE.txt +1 -1
  11. data/README.md +1293 -97
  12. data/Rakefile +369 -1
  13. data/benchmarks/README.md +1 -0
  14. data/benchmarks/dry_do_vs_fear_for.txt +11 -0
  15. data/benchmarks/dry_some_fmap_vs_fear_some_map.txt +11 -0
  16. data/benchmarks/factorial.txt +16 -0
  17. data/benchmarks/fear_gaurd_and1_vs_new.txt +13 -0
  18. data/benchmarks/fear_gaurd_and2_vs_and.txt +13 -0
  19. data/benchmarks/fear_gaurd_and3_vs_and_and.txt +13 -0
  20. data/benchmarks/fear_pattern_extracting_with_vs_without_cache.txt +11 -0
  21. data/benchmarks/fear_pattern_matching_construction_vs_execution.txt +13 -0
  22. data/benchmarks/pattern_matching_dry_vs_qo_vs_fear_try.txt +14 -0
  23. data/benchmarks/pattern_matching_qo_vs_fear_pattern_extraction.txt +11 -0
  24. data/benchmarks/pattern_matching_qo_vs_fear_try_execution.txt +11 -0
  25. data/examples/pattern_extracting.rb +17 -0
  26. data/examples/pattern_extracting_ruby2.7.rb +15 -0
  27. data/examples/pattern_matching_binary_tree_set.rb +101 -0
  28. data/examples/pattern_matching_number_in_words.rb +60 -0
  29. data/fear.gemspec +34 -23
  30. data/lib/dry/types/fear.rb +8 -0
  31. data/lib/dry/types/fear/option.rb +125 -0
  32. data/lib/fear.rb +65 -15
  33. data/lib/fear/await.rb +33 -0
  34. data/lib/fear/awaitable.rb +28 -0
  35. data/lib/fear/either.rb +131 -71
  36. data/lib/fear/either_api.rb +23 -0
  37. data/lib/fear/either_pattern_match.rb +53 -0
  38. data/lib/fear/empty_partial_function.rb +38 -0
  39. data/lib/fear/extractor.rb +112 -0
  40. data/lib/fear/extractor/anonymous_array_splat_matcher.rb +10 -0
  41. data/lib/fear/extractor/any_matcher.rb +17 -0
  42. data/lib/fear/extractor/array_head_matcher.rb +36 -0
  43. data/lib/fear/extractor/array_matcher.rb +40 -0
  44. data/lib/fear/extractor/array_splat_matcher.rb +16 -0
  45. data/lib/fear/extractor/empty_list_matcher.rb +20 -0
  46. data/lib/fear/extractor/extractor_matcher.rb +44 -0
  47. data/lib/fear/extractor/grammar.rb +203 -0
  48. data/lib/fear/extractor/grammar.treetop +129 -0
  49. data/lib/fear/extractor/identifier_matcher.rb +18 -0
  50. data/lib/fear/extractor/matcher.rb +53 -0
  51. data/lib/fear/extractor/matcher/and.rb +38 -0
  52. data/lib/fear/extractor/named_array_splat_matcher.rb +17 -0
  53. data/lib/fear/extractor/pattern.rb +58 -0
  54. data/lib/fear/extractor/typed_identifier_matcher.rb +26 -0
  55. data/lib/fear/extractor/value_matcher.rb +19 -0
  56. data/lib/fear/extractor_api.rb +35 -0
  57. data/lib/fear/failure.rb +46 -14
  58. data/lib/fear/failure_pattern_match.rb +10 -0
  59. data/lib/fear/for.rb +37 -95
  60. data/lib/fear/for_api.rb +68 -0
  61. data/lib/fear/future.rb +497 -0
  62. data/lib/fear/future_api.rb +21 -0
  63. data/lib/fear/left.rb +19 -2
  64. data/lib/fear/left_pattern_match.rb +11 -0
  65. data/lib/fear/none.rb +67 -3
  66. data/lib/fear/none_pattern_match.rb +14 -0
  67. data/lib/fear/option.rb +120 -56
  68. data/lib/fear/option_api.rb +40 -0
  69. data/lib/fear/option_pattern_match.rb +48 -0
  70. data/lib/fear/partial_function.rb +176 -0
  71. data/lib/fear/partial_function/and_then.rb +50 -0
  72. data/lib/fear/partial_function/any.rb +28 -0
  73. data/lib/fear/partial_function/combined.rb +53 -0
  74. data/lib/fear/partial_function/empty.rb +10 -0
  75. data/lib/fear/partial_function/guard.rb +80 -0
  76. data/lib/fear/partial_function/guard/and.rb +38 -0
  77. data/lib/fear/partial_function/guard/and3.rb +41 -0
  78. data/lib/fear/partial_function/guard/or.rb +38 -0
  79. data/lib/fear/partial_function/lifted.rb +23 -0
  80. data/lib/fear/partial_function/or_else.rb +64 -0
  81. data/lib/fear/partial_function_class.rb +38 -0
  82. data/lib/fear/pattern_match.rb +114 -0
  83. data/lib/fear/pattern_matching_api.rb +137 -0
  84. data/lib/fear/promise.rb +95 -0
  85. data/lib/fear/right.rb +20 -2
  86. data/lib/fear/right_biased.rb +6 -14
  87. data/lib/fear/right_pattern_match.rb +11 -0
  88. data/lib/fear/some.rb +55 -3
  89. data/lib/fear/some_pattern_match.rb +13 -0
  90. data/lib/fear/struct.rb +248 -0
  91. data/lib/fear/success.rb +35 -5
  92. data/lib/fear/success_pattern_match.rb +12 -0
  93. data/lib/fear/try.rb +136 -79
  94. data/lib/fear/try_api.rb +33 -0
  95. data/lib/fear/try_pattern_match.rb +33 -0
  96. data/lib/fear/unit.rb +32 -0
  97. data/lib/fear/utils.rb +39 -14
  98. data/lib/fear/version.rb +4 -1
  99. data/spec/dry/types/fear/option/constrained_spec.rb +22 -0
  100. data/spec/dry/types/fear/option/core_spec.rb +77 -0
  101. data/spec/dry/types/fear/option/default_spec.rb +21 -0
  102. data/spec/dry/types/fear/option/hash_spec.rb +58 -0
  103. data/spec/dry/types/fear/option/option_spec.rb +97 -0
  104. data/spec/fear/awaitable_spec.rb +17 -0
  105. data/spec/fear/done_spec.rb +8 -6
  106. data/spec/fear/either/mixin_spec.rb +17 -0
  107. data/spec/fear/either_pattern_match_spec.rb +37 -0
  108. data/spec/fear/either_pattern_matching_spec.rb +28 -0
  109. data/spec/fear/extractor/array_matcher_spec.rb +230 -0
  110. data/spec/fear/extractor/extractor_matcher_spec.rb +153 -0
  111. data/spec/fear/extractor/grammar_array_spec.rb +25 -0
  112. data/spec/fear/extractor/identified_matcher_spec.rb +49 -0
  113. data/spec/fear/extractor/identifier_matcher_spec.rb +68 -0
  114. data/spec/fear/extractor/pattern_spec.rb +34 -0
  115. data/spec/fear/extractor/typed_identifier_matcher_spec.rb +64 -0
  116. data/spec/fear/extractor/value_matcher_number_spec.rb +79 -0
  117. data/spec/fear/extractor/value_matcher_string_spec.rb +88 -0
  118. data/spec/fear/extractor/value_matcher_symbol_spec.rb +71 -0
  119. data/spec/fear/extractor_api_spec.rb +115 -0
  120. data/spec/fear/extractor_spec.rb +61 -0
  121. data/spec/fear/failure_spec.rb +145 -45
  122. data/spec/fear/for_spec.rb +57 -67
  123. data/spec/fear/future_spec.rb +691 -0
  124. data/spec/fear/guard_spec.rb +103 -0
  125. data/spec/fear/left_spec.rb +112 -46
  126. data/spec/fear/none_spec.rb +114 -16
  127. data/spec/fear/option/mixin_spec.rb +39 -0
  128. data/spec/fear/option_pattern_match_spec.rb +35 -0
  129. data/spec/fear/option_pattern_matching_spec.rb +34 -0
  130. data/spec/fear/option_spec.rb +121 -8
  131. data/spec/fear/partial_function/empty_spec.rb +38 -0
  132. data/spec/fear/partial_function_and_then_spec.rb +147 -0
  133. data/spec/fear/partial_function_composition_spec.rb +82 -0
  134. data/spec/fear/partial_function_or_else_spec.rb +276 -0
  135. data/spec/fear/partial_function_spec.rb +239 -0
  136. data/spec/fear/pattern_match_spec.rb +93 -0
  137. data/spec/fear/pattern_matching_api_spec.rb +31 -0
  138. data/spec/fear/promise_spec.rb +96 -0
  139. data/spec/fear/right_biased/left.rb +29 -32
  140. data/spec/fear/right_biased/right.rb +51 -54
  141. data/spec/fear/right_spec.rb +109 -41
  142. data/spec/fear/some_spec.rb +80 -15
  143. data/spec/fear/success_spec.rb +99 -32
  144. data/spec/fear/try/mixin_spec.rb +19 -0
  145. data/spec/fear/try_pattern_match_spec.rb +37 -0
  146. data/spec/fear/try_pattern_matching_spec.rb +34 -0
  147. data/spec/fear/utils_spec.rb +16 -14
  148. data/spec/spec_helper.rb +13 -7
  149. data/spec/struct_pattern_matching_spec.rb +36 -0
  150. data/spec/struct_spec.rb +226 -0
  151. data/spec/support/dry_types.rb +6 -0
  152. metadata +320 -29
  153. data/.travis.yml +0 -9
  154. data/lib/fear/done.rb +0 -22
  155. data/lib/fear/for/evaluation_context.rb +0 -91
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe Fear::Either::Mixin do
4
+ include Fear::Either::Mixin
5
+
6
+ describe "Left()" do
7
+ subject { Left(42) }
8
+
9
+ it { is_expected.to eq(Fear::Left.new(42)) }
10
+ end
11
+
12
+ describe "Right()" do
13
+ subject { Right(42) }
14
+
15
+ it { is_expected.to eq(Fear::Right.new(42)) }
16
+ end
17
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe Fear::EitherPatternMatch do
4
+ context "Right" do
5
+ let(:matcher) do
6
+ described_class.new do |m|
7
+ m.right(:even?.to_proc) { |x| "#{x} is even" }
8
+ m.right(:odd?.to_proc) { |x| "#{x} is odd" }
9
+ end
10
+ end
11
+
12
+ it do
13
+ expect(matcher.(Fear.right(4))).to eq("4 is even")
14
+ expect(matcher.(Fear.right(3))).to eq("3 is odd")
15
+ expect do
16
+ matcher.(Fear.left(44))
17
+ end.to raise_error(Fear::MatchError)
18
+ end
19
+ end
20
+
21
+ context "Left" do
22
+ let(:matcher) do
23
+ described_class.new do |m|
24
+ m.left(:even?.to_proc) { |x| "#{x} is even" }
25
+ m.left(:odd?.to_proc) { |x| "#{x} is odd" }
26
+ end
27
+ end
28
+
29
+ it do
30
+ expect(matcher.(Fear.left(4))).to eq("4 is even")
31
+ expect(matcher.(Fear.left(3))).to eq("3 is odd")
32
+ expect do
33
+ matcher.(Fear.right(44))
34
+ end.to raise_error(Fear::MatchError)
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe Fear::Either do
4
+ describe "pattern matching" do
5
+ subject do
6
+ case value
7
+ in Fear::Right[Integer => int]
8
+ "right of #{int}"
9
+ in Fear::Left[Integer => int]
10
+ "left of #{int}"
11
+ else
12
+ "something else"
13
+ end
14
+ end
15
+
16
+ context "when value is right of integer" do
17
+ let(:value) { Fear.right(42) }
18
+
19
+ it { is_expected.to eq("right of 42") }
20
+ end
21
+
22
+ context "when value is left of integer" do
23
+ let(:value) { Fear.left(42) }
24
+
25
+ it { is_expected.to eq("left of 42") }
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,230 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe Fear::Extractor::ArrayMatcher do
4
+ let(:parser) { Fear::Extractor::GrammarParser.new }
5
+ let(:matcher) { parser.parse(pattern).to_matcher }
6
+
7
+ describe "#defined_at?" do
8
+ subject { matcher }
9
+
10
+ context "empty array" do
11
+ let(:pattern) { "[]" }
12
+
13
+ it { is_expected.to be_defined_at([]) }
14
+ it { is_expected.not_to be_defined_at([1]) }
15
+ end
16
+
17
+ context "empty array with splat" do
18
+ let(:pattern) { "[*]" }
19
+
20
+ it { is_expected.to be_defined_at([]) }
21
+ it { is_expected.to be_defined_at([1]) }
22
+ it { is_expected.to be_defined_at([1, 2]) }
23
+ end
24
+
25
+ context "empty array with named splat" do
26
+ let(:pattern) { "[*var]" }
27
+
28
+ it { is_expected.to be_defined_at([]) }
29
+ it { is_expected.to be_defined_at([1]) }
30
+ it { is_expected.to be_defined_at([1, 2]) }
31
+ end
32
+
33
+ context "one element array" do
34
+ let(:pattern) { "[1]" }
35
+
36
+ it { is_expected.not_to be_defined_at([]) }
37
+ it { is_expected.to be_defined_at([1]) }
38
+ it { is_expected.not_to be_defined_at([1, 2]) }
39
+ it { is_expected.not_to be_defined_at([2, 1]) }
40
+
41
+ context "identifier" do
42
+ let(:pattern) { "[var]" }
43
+
44
+ it { is_expected.not_to be_defined_at([]) }
45
+ it { is_expected.to be_defined_at([1]) }
46
+ it { is_expected.to be_defined_at([[1]]) }
47
+ end
48
+ end
49
+
50
+ context "two elements array with nested matcher" do
51
+ let(:pattern) { "[[1, *], 1]" }
52
+
53
+ it { is_expected.not_to be_defined_at([]) }
54
+ it { is_expected.to be_defined_at([[1], 1]) }
55
+ it { is_expected.to be_defined_at([[1, 2], 1]) }
56
+ it { is_expected.not_to be_defined_at([[1, 2], 2]) }
57
+ it { is_expected.not_to be_defined_at([2, 1]) }
58
+ end
59
+
60
+ context "one element array with splat" do
61
+ let(:pattern) { "[1, *]" }
62
+
63
+ it { is_expected.not_to be_defined_at([]) }
64
+ it { is_expected.to be_defined_at([1]) }
65
+ it { is_expected.to be_defined_at([1, 2]) }
66
+ it { is_expected.to be_defined_at([1, 2, 3]) }
67
+ it { is_expected.not_to be_defined_at([2, 1]) }
68
+ end
69
+
70
+ context "one element array with named splat" do
71
+ let(:pattern) { "[1, *var]" }
72
+
73
+ it { is_expected.not_to be_defined_at([]) }
74
+ it { is_expected.to be_defined_at([1]) }
75
+ it { is_expected.to be_defined_at([1, 2]) }
76
+ it { is_expected.to be_defined_at([1, 2, 3]) }
77
+ it { is_expected.not_to be_defined_at([2, 1]) }
78
+ end
79
+
80
+ context "three elements array" do
81
+ context "with identifier in the middle" do
82
+ let(:pattern) { "[1, var, 2]" }
83
+
84
+ it { is_expected.not_to be_defined_at([]) }
85
+ it { is_expected.to be_defined_at([1, 3, 2]) }
86
+ it { is_expected.not_to be_defined_at([1, 2, 3]) }
87
+ it { is_expected.not_to be_defined_at([1, 2, 3, 4]) }
88
+ it { is_expected.not_to be_defined_at([1]) }
89
+ it { is_expected.not_to be_defined_at([2]) }
90
+ end
91
+
92
+ context "head and tail" do
93
+ let(:pattern) { "[head, *tail]" }
94
+
95
+ it { is_expected.not_to be_defined_at([]) }
96
+ it { is_expected.to be_defined_at([1, 3, 2]) }
97
+ end
98
+ end
99
+
100
+ context "two element array" do
101
+ let(:pattern) { "[ 1, 2 ]" }
102
+
103
+ it { is_expected.not_to be_defined_at([]) }
104
+ it { is_expected.to be_defined_at([1, 2]) }
105
+ it { is_expected.not_to be_defined_at([1]) }
106
+ it { is_expected.not_to be_defined_at([2]) }
107
+ it { is_expected.not_to be_defined_at([1, 3]) }
108
+ it { is_expected.not_to be_defined_at([2, 2]) }
109
+ it { is_expected.not_to be_defined_at([1, 2, 3]) }
110
+
111
+ context "with identifier at the beginning" do
112
+ let(:pattern) { "[var, 2]" }
113
+
114
+ it { is_expected.not_to be_defined_at([]) }
115
+ it { is_expected.to be_defined_at([1, 2]) }
116
+ it { is_expected.not_to be_defined_at([1, 3]) }
117
+ it { is_expected.not_to be_defined_at([1]) }
118
+ it { is_expected.not_to be_defined_at([2]) }
119
+ it { is_expected.not_to be_defined_at([1, 2, 3]) }
120
+ end
121
+ end
122
+ end
123
+
124
+ describe "#call" do
125
+ subject { matcher.(other) }
126
+
127
+ context "on the same array" do
128
+ let(:other) { [1] }
129
+ let(:pattern) { "[1]" }
130
+
131
+ it { is_expected.to eq({}) }
132
+ end
133
+
134
+ context "with splat on another array" do
135
+ let(:other) { [2, 1] }
136
+ let(:pattern) { "[2, *]" }
137
+
138
+ it { is_expected.to eq({}) }
139
+ end
140
+
141
+ context "with identifier at the middle of an array" do
142
+ let(:other) { [2, 1, 3] }
143
+ let(:pattern) { "[2, var, 3]" }
144
+
145
+ it { is_expected.to eq(var: 1) }
146
+ end
147
+
148
+ context "with identifier at the end of an array" do
149
+ let(:other) { [2, 1, 3] }
150
+ let(:pattern) { "[2, 1, var]" }
151
+
152
+ it { is_expected.to eq(var: 3) }
153
+ end
154
+
155
+ context "with named splat matching all the array" do
156
+ let(:other) { [2, 1, 3, 4] }
157
+ let(:pattern) { "[*var]" }
158
+
159
+ it { is_expected.to eq(var: [2, 1, 3, 4]) }
160
+ end
161
+
162
+ context "with named splat matching tail of an array" do
163
+ let(:other) { [2, 1, 3, 4] }
164
+ let(:pattern) { "[2, 1, *var]" }
165
+
166
+ it { is_expected.to eq(var: [3, 4]) }
167
+ end
168
+
169
+ context "with named splat at the end of an array" do
170
+ let(:other) { [2, 1] }
171
+ let(:pattern) { "[2, 1, *var]" }
172
+
173
+ it { is_expected.to eq(var: []) }
174
+ end
175
+
176
+ context "with several identifiers in an array" do
177
+ let(:other) { [2, 1, 3] }
178
+ let(:pattern) { "[a, 1, b]" }
179
+
180
+ it { is_expected.to eq(a: 2, b: 3) }
181
+ end
182
+
183
+ context "head and tail" do
184
+ let(:other) { [2, 1, 3] }
185
+ let(:pattern) { "[head, *tail]" }
186
+
187
+ it { is_expected.to eq(head: 2, tail: [1, 3]) }
188
+ end
189
+
190
+ context "ignore head, capture tail" do
191
+ let(:other) { [2, 1, 3] }
192
+ let(:pattern) { "[_, *tail]" }
193
+
194
+ it { is_expected.to eq(tail: [1, 3]) }
195
+ end
196
+ end
197
+
198
+ describe "#failure_reason" do
199
+ subject { matcher.failure_reason(other) }
200
+
201
+ context "on the same array" do
202
+ let(:other) { [1] }
203
+ let(:pattern) { "[1]" }
204
+
205
+ it { is_expected.to eq(Fear.none) }
206
+ end
207
+
208
+ context "on another array" do
209
+ let(:other) { [2, 1] }
210
+ let(:pattern) { "[2, 2]" }
211
+
212
+ it { is_expected.to eq(Fear.some(<<~ERROR.strip)) }
213
+ Expected `1` to match:
214
+ [2, 2]
215
+ ~~~~^
216
+ ERROR
217
+ end
218
+
219
+ context "element type mismatch" do
220
+ let(:other) { [2, 1] }
221
+ let(:pattern) { "[[2], 1]" }
222
+
223
+ it { is_expected.to eq(Fear.some(<<~ERROR.strip)) }
224
+ Expected `2` to match:
225
+ [[2], 1]
226
+ ~~^
227
+ ERROR
228
+ end
229
+ end
230
+ end
@@ -0,0 +1,153 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe Fear::Extractor::ExtractorMatcher do
4
+ let(:parser) { Fear::Extractor::GrammarParser.new }
5
+ let(:matcher) { parser.parse(pattern).to_matcher }
6
+
7
+ describe "#defined_at?" do
8
+ subject { matcher }
9
+
10
+ context "boolean extractor" do
11
+ let(:pattern) { "IsEven()" }
12
+
13
+ it { is_expected.to be_defined_at(42) }
14
+ it { is_expected.not_to be_defined_at(43) }
15
+ it { is_expected.not_to be_defined_at("foo") }
16
+ end
17
+
18
+ context "single argument extractor" do
19
+ let(:pattern) { "Fear::Some(a : Integer)" }
20
+
21
+ it { is_expected.to be_defined_at(Fear.some(42)) }
22
+ it { is_expected.not_to be_defined_at("foo") }
23
+ it { is_expected.not_to be_defined_at(Fear.some("foo")) }
24
+ end
25
+
26
+ context "single argument extractor with array as an argument" do
27
+ let(:pattern) { "Fear::Some([1, 2])" }
28
+
29
+ it { is_expected.to be_defined_at(Fear.some([1, 2])) }
30
+ it { is_expected.not_to be_defined_at(Fear.some([1, 1])) }
31
+ it { is_expected.not_to be_defined_at(Fear.some("foo")) }
32
+ end
33
+
34
+ context "multiple arguments extractor" do
35
+ let(:pattern) { "Date(2017, month, _)" }
36
+
37
+ it { is_expected.to be_defined_at(Date.parse("2017-02-15")) }
38
+ it { is_expected.not_to be_defined_at(Date.parse("2018-02-15")) }
39
+ it { is_expected.not_to be_defined_at("foo") }
40
+ end
41
+
42
+ context "Struct" do
43
+ StructDate = ::Struct.new(:year, :month, :day)
44
+
45
+ let(:pattern) { "StructDate(2017, month, _)" }
46
+
47
+ it { is_expected.to be_defined_at(StructDate.new(2017, 2, 15)) }
48
+ it { is_expected.not_to be_defined_at(StructDate.new(2018, 2, 15)) }
49
+ end
50
+ end
51
+
52
+ describe "#call" do
53
+ subject { matcher.(other) }
54
+
55
+ context "single argument extractor" do
56
+ let(:pattern) { "Fear::Some(a : Integer)" }
57
+ let(:other) { Fear.some(42) }
58
+
59
+ it { is_expected.to eq(a: 42) }
60
+ end
61
+
62
+ context "multiple arguments extractor" do
63
+ let(:pattern) { "Date(2017, month, day)" }
64
+ let(:other) { Date.parse("2017-02-15") }
65
+
66
+ it { is_expected.to eq(month: 2, day: 15) }
67
+ end
68
+ end
69
+
70
+ describe "#failure_reason" do
71
+ subject { matcher.failure_reason(other) }
72
+
73
+ context "no argument extractor" do
74
+ let(:pattern) { "IsEven()" }
75
+
76
+ context "defined" do
77
+ let(:other) { 42 }
78
+
79
+ it { is_expected.to eq(Fear.none) }
80
+ end
81
+
82
+ context "not defined" do
83
+ let(:other) { 43 }
84
+
85
+ it { is_expected.to eq(Fear.some(<<~MSG.strip)) }
86
+ Expected `43` to match:
87
+ IsEven()
88
+ ^
89
+ MSG
90
+ end
91
+ end
92
+
93
+ context "single argument extractor" do
94
+ let(:pattern) { "Fear::Some(a : Integer)" }
95
+
96
+ context "defined" do
97
+ let(:other) { Fear.some(42) }
98
+
99
+ it { is_expected.to eq(Fear.none) }
100
+ end
101
+
102
+ context "not defined" do
103
+ let(:other) { Fear.some("42") }
104
+
105
+ it { is_expected.to eq(Fear.some(<<~MSG.strip)) }
106
+ Expected `"42"` to match:
107
+ Fear::Some(a : Integer)
108
+ ~~~~~~~~~~~~~~~^
109
+ MSG
110
+ end
111
+ end
112
+
113
+ context "single argument extractor, array argument" do
114
+ let(:pattern) { "Fear::Some([1, 2])" }
115
+
116
+ context "defined" do
117
+ let(:other) { Fear.some([1, 2]) }
118
+
119
+ it { is_expected.to eq(Fear.none) }
120
+ end
121
+
122
+ context "not defined" do
123
+ let(:other) { Fear.some([1, 1]) }
124
+
125
+ it { is_expected.to eq(Fear.some(<<~MSG.strip)) }
126
+ Expected `1` to match:
127
+ Fear::Some([1, 2])
128
+ ~~~~~~~~~~~~~~~^
129
+ MSG
130
+ end
131
+ end
132
+
133
+ context "multiple arguments extractor" do
134
+ let(:pattern) { "Date(year, 02, day)" }
135
+
136
+ context "defined" do
137
+ let(:other) { Date.parse("2017-02-15") }
138
+
139
+ it { is_expected.to eq(Fear.none) }
140
+ end
141
+
142
+ context "not defined" do
143
+ let(:other) { Date.parse("2017-04-15") }
144
+
145
+ it { is_expected.to eq(Fear.some(<<~MSG.strip)) }
146
+ Expected `4` to match:
147
+ Date(year, 02, day)
148
+ ~~~~~~~~~~~^
149
+ MSG
150
+ end
151
+ end
152
+ end
153
+ end