fear 0.11.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (110) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +0 -1
  3. data/.rubocop.yml +18 -0
  4. data/.travis.yml +0 -3
  5. data/CHANGELOG.md +12 -1
  6. data/Gemfile +1 -0
  7. data/{gemfiles/dry_equalizer_0.2.1.gemfile.lock → Gemfile.lock} +21 -12
  8. data/README.md +594 -241
  9. data/Rakefile +166 -219
  10. data/benchmarks/README.md +1 -0
  11. data/benchmarks/dry_do_vs_fear_for.txt +11 -0
  12. data/benchmarks/dry_some_fmap_vs_fear_some_map.txt +11 -0
  13. data/benchmarks/factorial.txt +16 -0
  14. data/benchmarks/fear_gaurd_and1_vs_new.txt +13 -0
  15. data/benchmarks/fear_gaurd_and2_vs_and.txt +13 -0
  16. data/benchmarks/fear_gaurd_and3_vs_and_and.txt +13 -0
  17. data/benchmarks/fear_pattern_extracting_with_vs_without_cache.txt +11 -0
  18. data/benchmarks/fear_pattern_matching_construction_vs_execution.txt +13 -0
  19. data/benchmarks/pattern_matching_dry_vs_qo_vs_fear_try.txt +14 -0
  20. data/benchmarks/pattern_matching_qo_vs_fear_pattern_extraction.txt +11 -0
  21. data/benchmarks/pattern_matching_qo_vs_fear_try_execution.txt +11 -0
  22. data/examples/pattern_extracting.rb +15 -0
  23. data/examples/pattern_matching_binary_tree_set.rb +96 -0
  24. data/examples/pattern_matching_number_in_words.rb +54 -0
  25. data/fear.gemspec +4 -2
  26. data/lib/fear.rb +21 -4
  27. data/lib/fear/either.rb +77 -59
  28. data/lib/fear/either_api.rb +21 -0
  29. data/lib/fear/empty_partial_function.rb +1 -1
  30. data/lib/fear/extractor.rb +108 -0
  31. data/lib/fear/extractor/anonymous_array_splat_matcher.rb +8 -0
  32. data/lib/fear/extractor/any_matcher.rb +15 -0
  33. data/lib/fear/extractor/array_head_matcher.rb +34 -0
  34. data/lib/fear/extractor/array_matcher.rb +38 -0
  35. data/lib/fear/extractor/array_splat_matcher.rb +14 -0
  36. data/lib/fear/extractor/empty_list_matcher.rb +18 -0
  37. data/lib/fear/extractor/extractor_matcher.rb +42 -0
  38. data/lib/fear/extractor/grammar.rb +201 -0
  39. data/lib/fear/extractor/grammar.treetop +129 -0
  40. data/lib/fear/extractor/identifier_matcher.rb +16 -0
  41. data/lib/fear/extractor/matcher.rb +54 -0
  42. data/lib/fear/extractor/matcher/and.rb +36 -0
  43. data/lib/fear/extractor/named_array_splat_matcher.rb +15 -0
  44. data/lib/fear/extractor/pattern.rb +55 -0
  45. data/lib/fear/extractor/typed_identifier_matcher.rb +24 -0
  46. data/lib/fear/extractor/value_matcher.rb +17 -0
  47. data/lib/fear/extractor_api.rb +33 -0
  48. data/lib/fear/failure.rb +32 -10
  49. data/lib/fear/for.rb +14 -69
  50. data/lib/fear/for_api.rb +66 -0
  51. data/lib/fear/future.rb +414 -0
  52. data/lib/fear/future_api.rb +19 -0
  53. data/lib/fear/left.rb +8 -0
  54. data/lib/fear/none.rb +17 -8
  55. data/lib/fear/option.rb +55 -49
  56. data/lib/fear/option_api.rb +38 -0
  57. data/lib/fear/partial_function.rb +9 -12
  58. data/lib/fear/partial_function/empty.rb +1 -1
  59. data/lib/fear/partial_function/guard.rb +8 -20
  60. data/lib/fear/partial_function/lifted.rb +1 -0
  61. data/lib/fear/partial_function_class.rb +10 -0
  62. data/lib/fear/pattern_match.rb +10 -0
  63. data/lib/fear/pattern_matching_api.rb +35 -11
  64. data/lib/fear/promise.rb +87 -0
  65. data/lib/fear/right.rb +8 -0
  66. data/lib/fear/some.rb +22 -3
  67. data/lib/fear/success.rb +22 -1
  68. data/lib/fear/try.rb +82 -67
  69. data/lib/fear/try_api.rb +31 -0
  70. data/lib/fear/unit.rb +28 -0
  71. data/lib/fear/version.rb +1 -1
  72. data/spec/fear/done_spec.rb +3 -3
  73. data/spec/fear/either/mixin_spec.rb +15 -0
  74. data/spec/fear/either_pattern_match_spec.rb +10 -12
  75. data/spec/fear/extractor/array_matcher_spec.rb +228 -0
  76. data/spec/fear/extractor/extractor_matcher_spec.rb +151 -0
  77. data/spec/fear/extractor/grammar_array_spec.rb +23 -0
  78. data/spec/fear/extractor/identified_matcher_spec.rb +47 -0
  79. data/spec/fear/extractor/identifier_matcher_spec.rb +66 -0
  80. data/spec/fear/extractor/pattern_spec.rb +32 -0
  81. data/spec/fear/extractor/typed_identifier_matcher_spec.rb +62 -0
  82. data/spec/fear/extractor/value_matcher_number_spec.rb +77 -0
  83. data/spec/fear/extractor/value_matcher_string_spec.rb +86 -0
  84. data/spec/fear/extractor/value_matcher_symbol_spec.rb +69 -0
  85. data/spec/fear/extractor_api_spec.rb +113 -0
  86. data/spec/fear/extractor_spec.rb +59 -0
  87. data/spec/fear/failure_spec.rb +73 -13
  88. data/spec/fear/for_spec.rb +35 -35
  89. data/spec/fear/future_spec.rb +466 -0
  90. data/spec/fear/guard_spec.rb +4 -4
  91. data/spec/fear/left_spec.rb +40 -14
  92. data/spec/fear/none_spec.rb +28 -12
  93. data/spec/fear/option/mixin_spec.rb +37 -0
  94. data/spec/fear/option_pattern_match_spec.rb +7 -9
  95. data/spec/fear/partial_function_spec.rb +25 -3
  96. data/spec/fear/pattern_match_spec.rb +33 -1
  97. data/spec/fear/promise_spec.rb +94 -0
  98. data/spec/fear/right_spec.rb +37 -9
  99. data/spec/fear/some_spec.rb +32 -6
  100. data/spec/fear/success_spec.rb +32 -4
  101. data/spec/fear/try/mixin_spec.rb +17 -0
  102. data/spec/fear/try_pattern_match_spec.rb +8 -10
  103. data/spec/spec_helper.rb +1 -1
  104. metadata +115 -20
  105. data/Appraisals +0 -32
  106. data/gemfiles/dry_equalizer_0.1.0.gemfile +0 -8
  107. data/gemfiles/dry_equalizer_0.1.0.gemfile.lock +0 -82
  108. data/gemfiles/dry_equalizer_0.2.1.gemfile +0 -8
  109. data/lib/fear/done.rb +0 -22
  110. data/spec/fear/option_spec.rb +0 -15
@@ -0,0 +1,31 @@
1
+ module Fear
2
+ module TryApi
3
+ # Constructs a +Try+ using the block. This
4
+ # method ensures any non-fatal exception is caught and a
5
+ # +Failure+ object is returned.
6
+ # @return [Fear::Try]
7
+ # @example
8
+ # Fear.try { 4/0 } #=> #<Fear::Failure exception=#<ZeroDivisionError: divided by 0>>
9
+ # Fear.try { 4/2 } #=> #<Fear::Success value=2>
10
+ #
11
+ def try
12
+ success(yield)
13
+ rescue StandardError => error
14
+ failure(error)
15
+ end
16
+
17
+ # @param exception [StandardError]
18
+ # @return [Fear::Failure]
19
+ #
20
+ def failure(exception)
21
+ Fear::Failure.new(exception)
22
+ end
23
+
24
+ # @param value [any]
25
+ # @return [Fear::Success]
26
+ #
27
+ def success(value)
28
+ Fear::Success.new(value)
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,28 @@
1
+ module Fear
2
+ # Represents lack of value. It's typically returned when function completed without a value.
3
+ #
4
+ # @example
5
+ # if user.valid?
6
+ # Fear.right(Fear::Unit)
7
+ # else
8
+ # Fear.left(user.errors)
9
+ # end
10
+ #
11
+ # @example
12
+ # def sent_notifications(user)
13
+ # # ...
14
+ # Fear::Unit
15
+ # end
16
+ #
17
+ Unit = Object.new.tap do |unit|
18
+ # @return [String]
19
+ def unit.to_s
20
+ '#<Fear::Unit>'
21
+ end
22
+
23
+ # @return [String]
24
+ def unit.inspect
25
+ '#<Fear::Unit>'
26
+ end
27
+ end.freeze
28
+ end
@@ -1,3 +1,3 @@
1
1
  module Fear
2
- VERSION = '0.11.0'.freeze
2
+ VERSION = '1.0.0'.freeze
3
3
  end
@@ -1,14 +1,14 @@
1
- RSpec.describe Fear::Done do
1
+ RSpec.describe Fear::Unit do
2
2
  describe '#to_s' do
3
3
  subject { described_class.to_s }
4
4
 
5
- it { is_expected.to eq('Done') }
5
+ it { is_expected.to eq('#<Fear::Unit>') }
6
6
  end
7
7
 
8
8
  describe '#inspect' do
9
9
  subject { described_class.inspect }
10
10
 
11
- it { is_expected.to eq('Done') }
11
+ it { is_expected.to eq('#<Fear::Unit>') }
12
12
  end
13
13
 
14
14
  describe '#==' do
@@ -0,0 +1,15 @@
1
+ RSpec.describe Fear::Either::Mixin do
2
+ include Fear::Either::Mixin
3
+
4
+ describe 'Left()' do
5
+ subject { Left(42) }
6
+
7
+ it { is_expected.to eq(Fear::Left.new(42)) }
8
+ end
9
+
10
+ describe 'Right()' do
11
+ subject { Right(42) }
12
+
13
+ it { is_expected.to eq(Fear::Right.new(42)) }
14
+ end
15
+ end
@@ -1,19 +1,17 @@
1
1
  RSpec.describe Fear::EitherPatternMatch do
2
- include Fear::Either::Mixin
3
-
4
2
  context 'Right' do
5
3
  let(:matcher) do
6
4
  described_class.new do |m|
7
- m.right(:even?) { |x| "#{x} is even" }
8
- m.right(:odd?) { |x| "#{x} is odd" }
5
+ m.right(:even?.to_proc) { |x| "#{x} is even" }
6
+ m.right(:odd?.to_proc) { |x| "#{x} is odd" }
9
7
  end
10
8
  end
11
9
 
12
10
  it do
13
- expect(matcher.call(Right(4))).to eq('4 is even')
14
- expect(matcher.call(Right(3))).to eq('3 is odd')
11
+ expect(matcher.call(Fear.right(4))).to eq('4 is even')
12
+ expect(matcher.call(Fear.right(3))).to eq('3 is odd')
15
13
  expect do
16
- matcher.call(Left(44))
14
+ matcher.call(Fear.left(44))
17
15
  end.to raise_error(Fear::MatchError)
18
16
  end
19
17
  end
@@ -21,16 +19,16 @@ RSpec.describe Fear::EitherPatternMatch do
21
19
  context 'Left' do
22
20
  let(:matcher) do
23
21
  described_class.new do |m|
24
- m.left(:even?) { |x| "#{x} is even" }
25
- m.left(:odd?) { |x| "#{x} is odd" }
22
+ m.left(:even?.to_proc) { |x| "#{x} is even" }
23
+ m.left(:odd?.to_proc) { |x| "#{x} is odd" }
26
24
  end
27
25
  end
28
26
 
29
27
  it do
30
- expect(matcher.call(Left(4))).to eq('4 is even')
31
- expect(matcher.call(Left(3))).to eq('3 is odd')
28
+ expect(matcher.call(Fear.left(4))).to eq('4 is even')
29
+ expect(matcher.call(Fear.left(3))).to eq('3 is odd')
32
30
  expect do
33
- matcher.call(Right(44))
31
+ matcher.call(Fear.right(44))
34
32
  end.to raise_error(Fear::MatchError)
35
33
  end
36
34
  end
@@ -0,0 +1,228 @@
1
+ RSpec.describe Fear::Extractor::ArrayMatcher do
2
+ let(:parser) { Fear::Extractor::GrammarParser.new }
3
+ let(:matcher) { parser.parse(pattern).to_matcher }
4
+
5
+ describe '#defined_at?' do
6
+ subject { matcher }
7
+
8
+ context 'empty array' do
9
+ let(:pattern) { '[]' }
10
+
11
+ it { is_expected.to be_defined_at([]) }
12
+ it { is_expected.not_to be_defined_at([1]) }
13
+ end
14
+
15
+ context 'empty array with splat' do
16
+ let(:pattern) { '[*]' }
17
+
18
+ it { is_expected.to be_defined_at([]) }
19
+ it { is_expected.to be_defined_at([1]) }
20
+ it { is_expected.to be_defined_at([1, 2]) }
21
+ end
22
+
23
+ context 'empty array with named splat' do
24
+ let(:pattern) { '[*var]' }
25
+
26
+ it { is_expected.to be_defined_at([]) }
27
+ it { is_expected.to be_defined_at([1]) }
28
+ it { is_expected.to be_defined_at([1, 2]) }
29
+ end
30
+
31
+ context 'one element array' do
32
+ let(:pattern) { '[1]' }
33
+
34
+ it { is_expected.not_to be_defined_at([]) }
35
+ it { is_expected.to be_defined_at([1]) }
36
+ it { is_expected.not_to be_defined_at([1, 2]) }
37
+ it { is_expected.not_to be_defined_at([2, 1]) }
38
+
39
+ context 'identifier' do
40
+ let(:pattern) { '[var]' }
41
+
42
+ it { is_expected.not_to be_defined_at([]) }
43
+ it { is_expected.to be_defined_at([1]) }
44
+ it { is_expected.to be_defined_at([[1]]) }
45
+ end
46
+ end
47
+
48
+ context 'two elements array with nested matcher' do
49
+ let(:pattern) { '[[1, *], 1]' }
50
+
51
+ it { is_expected.not_to be_defined_at([]) }
52
+ it { is_expected.to be_defined_at([[1], 1]) }
53
+ it { is_expected.to be_defined_at([[1, 2], 1]) }
54
+ it { is_expected.not_to be_defined_at([[1, 2], 2]) }
55
+ it { is_expected.not_to be_defined_at([2, 1]) }
56
+ end
57
+
58
+ context 'one element array with splat' do
59
+ let(:pattern) { '[1, *]' }
60
+
61
+ it { is_expected.not_to be_defined_at([]) }
62
+ it { is_expected.to be_defined_at([1]) }
63
+ it { is_expected.to be_defined_at([1, 2]) }
64
+ it { is_expected.to be_defined_at([1, 2, 3]) }
65
+ it { is_expected.not_to be_defined_at([2, 1]) }
66
+ end
67
+
68
+ context 'one element array with named splat' do
69
+ let(:pattern) { '[1, *var]' }
70
+
71
+ it { is_expected.not_to be_defined_at([]) }
72
+ it { is_expected.to be_defined_at([1]) }
73
+ it { is_expected.to be_defined_at([1, 2]) }
74
+ it { is_expected.to be_defined_at([1, 2, 3]) }
75
+ it { is_expected.not_to be_defined_at([2, 1]) }
76
+ end
77
+
78
+ context 'three elements array' do
79
+ context 'with identifier in the middle' do
80
+ let(:pattern) { '[1, var, 2]' }
81
+
82
+ it { is_expected.not_to be_defined_at([]) }
83
+ it { is_expected.to be_defined_at([1, 3, 2]) }
84
+ it { is_expected.not_to be_defined_at([1, 2, 3]) }
85
+ it { is_expected.not_to be_defined_at([1, 2, 3, 4]) }
86
+ it { is_expected.not_to be_defined_at([1]) }
87
+ it { is_expected.not_to be_defined_at([2]) }
88
+ end
89
+
90
+ context 'head and tail' do
91
+ let(:pattern) { '[head, *tail]' }
92
+
93
+ it { is_expected.not_to be_defined_at([]) }
94
+ it { is_expected.to be_defined_at([1, 3, 2]) }
95
+ end
96
+ end
97
+
98
+ context 'two element array' do
99
+ let(:pattern) { '[ 1, 2 ]' }
100
+
101
+ it { is_expected.not_to be_defined_at([]) }
102
+ it { is_expected.to be_defined_at([1, 2]) }
103
+ it { is_expected.not_to be_defined_at([1]) }
104
+ it { is_expected.not_to be_defined_at([2]) }
105
+ it { is_expected.not_to be_defined_at([1, 3]) }
106
+ it { is_expected.not_to be_defined_at([2, 2]) }
107
+ it { is_expected.not_to be_defined_at([1, 2, 3]) }
108
+
109
+ context 'with identifier at the beginning' do
110
+ let(:pattern) { '[var, 2]' }
111
+
112
+ it { is_expected.not_to be_defined_at([]) }
113
+ it { is_expected.to be_defined_at([1, 2]) }
114
+ it { is_expected.not_to be_defined_at([1, 3]) }
115
+ it { is_expected.not_to be_defined_at([1]) }
116
+ it { is_expected.not_to be_defined_at([2]) }
117
+ it { is_expected.not_to be_defined_at([1, 2, 3]) }
118
+ end
119
+ end
120
+ end
121
+
122
+ describe '#call' do
123
+ subject { matcher.call(other) }
124
+
125
+ context 'on the same array' do
126
+ let(:other) { [1] }
127
+ let(:pattern) { '[1]' }
128
+
129
+ it { is_expected.to eq({}) }
130
+ end
131
+
132
+ context 'with splat on another array' do
133
+ let(:other) { [2, 1] }
134
+ let(:pattern) { '[2, *]' }
135
+
136
+ it { is_expected.to eq({}) }
137
+ end
138
+
139
+ context 'with identifier at the middle of an array' do
140
+ let(:other) { [2, 1, 3] }
141
+ let(:pattern) { '[2, var, 3]' }
142
+
143
+ it { is_expected.to eq(var: 1) }
144
+ end
145
+
146
+ context 'with identifier at the end of an array' do
147
+ let(:other) { [2, 1, 3] }
148
+ let(:pattern) { '[2, 1, var]' }
149
+
150
+ it { is_expected.to eq(var: 3) }
151
+ end
152
+
153
+ context 'with named splat matching all the array' do
154
+ let(:other) { [2, 1, 3, 4] }
155
+ let(:pattern) { '[*var]' }
156
+
157
+ it { is_expected.to eq(var: [2, 1, 3, 4]) }
158
+ end
159
+
160
+ context 'with named splat matching tail of an array' do
161
+ let(:other) { [2, 1, 3, 4] }
162
+ let(:pattern) { '[2, 1, *var]' }
163
+
164
+ it { is_expected.to eq(var: [3, 4]) }
165
+ end
166
+
167
+ context 'with named splat at the end of an array' do
168
+ let(:other) { [2, 1] }
169
+ let(:pattern) { '[2, 1, *var]' }
170
+
171
+ it { is_expected.to eq(var: []) }
172
+ end
173
+
174
+ context 'with several identifiers in an array' do
175
+ let(:other) { [2, 1, 3] }
176
+ let(:pattern) { '[a, 1, b]' }
177
+
178
+ it { is_expected.to eq(a: 2, b: 3) }
179
+ end
180
+
181
+ context 'head and tail' do
182
+ let(:other) { [2, 1, 3] }
183
+ let(:pattern) { '[head, *tail]' }
184
+
185
+ it { is_expected.to eq(head: 2, tail: [1, 3]) }
186
+ end
187
+
188
+ context 'ignore head, capture tail' do
189
+ let(:other) { [2, 1, 3] }
190
+ let(:pattern) { '[_, *tail]' }
191
+
192
+ it { is_expected.to eq(tail: [1, 3]) }
193
+ end
194
+ end
195
+
196
+ describe '#failure_reason' do
197
+ subject { matcher.failure_reason(other) }
198
+
199
+ context 'on the same array' do
200
+ let(:other) { [1] }
201
+ let(:pattern) { '[1]' }
202
+
203
+ it { is_expected.to eq(Fear.none) }
204
+ end
205
+
206
+ context 'on another array' do
207
+ let(:other) { [2, 1] }
208
+ let(:pattern) { '[2, 2]' }
209
+
210
+ it { is_expected.to eq(Fear.some(<<-ERROR.strip)) }
211
+ Expected `1` to match:
212
+ [2, 2]
213
+ ~~~~^
214
+ ERROR
215
+ end
216
+
217
+ context 'element type mismatch' do
218
+ let(:other) { [2, 1] }
219
+ let(:pattern) { '[[2], 1]' }
220
+
221
+ it { is_expected.to eq(Fear.some(<<-ERROR.strip)) }
222
+ Expected `2` to match:
223
+ [[2], 1]
224
+ ~~^
225
+ ERROR
226
+ end
227
+ end
228
+ end
@@ -0,0 +1,151 @@
1
+ RSpec.describe Fear::Extractor::ExtractorMatcher do
2
+ let(:parser) { Fear::Extractor::GrammarParser.new }
3
+ let(:matcher) { parser.parse(pattern).to_matcher }
4
+
5
+ describe '#defined_at?' do
6
+ subject { matcher }
7
+
8
+ context 'boolean extractor' do
9
+ let(:pattern) { 'IsEven()' }
10
+
11
+ it { is_expected.to be_defined_at(42) }
12
+ it { is_expected.not_to be_defined_at(43) }
13
+ it { is_expected.not_to be_defined_at('foo') }
14
+ end
15
+
16
+ context 'single argument extractor' do
17
+ let(:pattern) { 'Fear::Some(a : Integer)' }
18
+
19
+ it { is_expected.to be_defined_at(Fear.some(42)) }
20
+ it { is_expected.not_to be_defined_at('foo') }
21
+ it { is_expected.not_to be_defined_at(Fear.some('foo')) }
22
+ end
23
+
24
+ context 'single argument extractor with array as an argument' do
25
+ let(:pattern) { 'Fear::Some([1, 2])' }
26
+
27
+ it { is_expected.to be_defined_at(Fear.some([1, 2])) }
28
+ it { is_expected.not_to be_defined_at(Fear.some([1, 1])) }
29
+ it { is_expected.not_to be_defined_at(Fear.some('foo')) }
30
+ end
31
+
32
+ context 'multiple arguments extractor' do
33
+ let(:pattern) { 'Date(2017, month, _)' }
34
+
35
+ it { is_expected.to be_defined_at(Date.parse('2017-02-15')) }
36
+ it { is_expected.not_to be_defined_at(Date.parse('2018-02-15')) }
37
+ it { is_expected.not_to be_defined_at('foo') }
38
+ end
39
+
40
+ context 'Struct' do
41
+ StructDate = Struct.new(:year, :month, :day)
42
+
43
+ let(:pattern) { 'StructDate(2017, month, _)' }
44
+
45
+ it { is_expected.to be_defined_at(StructDate.new(2017, 2, 15)) }
46
+ it { is_expected.not_to be_defined_at(StructDate.new(2018, 2, 15)) }
47
+ end
48
+ end
49
+
50
+ describe '#call' do
51
+ subject { matcher.call(other) }
52
+
53
+ context 'single argument extractor' do
54
+ let(:pattern) { 'Fear::Some(a : Integer)' }
55
+ let(:other) { Fear.some(42) }
56
+
57
+ it { is_expected.to eq(a: 42) }
58
+ end
59
+
60
+ context 'multiple arguments extractor' do
61
+ let(:pattern) { 'Date(2017, month, day)' }
62
+ let(:other) { Date.parse('2017-02-15') }
63
+
64
+ it { is_expected.to eq(month: 2, day: 15) }
65
+ end
66
+ end
67
+
68
+ describe '#failure_reason' do
69
+ subject { matcher.failure_reason(other) }
70
+
71
+ context 'no argument extractor' do
72
+ let(:pattern) { 'IsEven()' }
73
+
74
+ context 'defined' do
75
+ let(:other) { 42 }
76
+
77
+ it { is_expected.to eq(Fear.none) }
78
+ end
79
+
80
+ context 'not defined' do
81
+ let(:other) { 43 }
82
+
83
+ it { is_expected.to eq(Fear.some(<<-MSG.strip)) }
84
+ Expected `43` to match:
85
+ IsEven()
86
+ ^
87
+ MSG
88
+ end
89
+ end
90
+
91
+ context 'single argument extractor' do
92
+ let(:pattern) { 'Fear::Some(a : Integer)' }
93
+
94
+ context 'defined' do
95
+ let(:other) { Fear.some(42) }
96
+
97
+ it { is_expected.to eq(Fear.none) }
98
+ end
99
+
100
+ context 'not defined' do
101
+ let(:other) { Fear.some('42') }
102
+
103
+ it { is_expected.to eq(Fear.some(<<-MSG.strip)) }
104
+ Expected `"42"` to match:
105
+ Fear::Some(a : Integer)
106
+ ~~~~~~~~~~~~~~~^
107
+ MSG
108
+ end
109
+ end
110
+
111
+ context 'single argument extractor, array argument' do
112
+ let(:pattern) { 'Fear::Some([1, 2])' }
113
+
114
+ context 'defined' do
115
+ let(:other) { Fear.some([1, 2]) }
116
+
117
+ it { is_expected.to eq(Fear.none) }
118
+ end
119
+
120
+ context 'not defined' do
121
+ let(:other) { Fear.some([1, 1]) }
122
+
123
+ it { is_expected.to eq(Fear.some(<<-MSG.strip)) }
124
+ Expected `1` to match:
125
+ Fear::Some([1, 2])
126
+ ~~~~~~~~~~~~~~~^
127
+ MSG
128
+ end
129
+ end
130
+
131
+ context 'multiple arguments extractor' do
132
+ let(:pattern) { 'Date(year, 02, day)' }
133
+
134
+ context 'defined' do
135
+ let(:other) { Date.parse('2017-02-15') }
136
+
137
+ it { is_expected.to eq(Fear.none) }
138
+ end
139
+
140
+ context 'not defined' do
141
+ let(:other) { Date.parse('2017-04-15') }
142
+
143
+ it { is_expected.to eq(Fear.some(<<-MSG.strip)) }
144
+ Expected `4` to match:
145
+ Date(year, 02, day)
146
+ ~~~~~~~~~~~^
147
+ MSG
148
+ end
149
+ end
150
+ end
151
+ end