functional-ruby 0.7.7 → 1.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.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +92 -152
  3. data/doc/memo.txt +192 -0
  4. data/doc/pattern_matching.txt +485 -0
  5. data/doc/protocol.txt +221 -0
  6. data/doc/record.txt +144 -0
  7. data/doc/thread_safety.txt +8 -0
  8. data/lib/functional.rb +48 -18
  9. data/lib/functional/abstract_struct.rb +161 -0
  10. data/lib/functional/delay.rb +117 -0
  11. data/lib/functional/either.rb +222 -0
  12. data/lib/functional/memo.rb +93 -0
  13. data/lib/functional/method_signature.rb +72 -0
  14. data/lib/functional/option.rb +209 -0
  15. data/lib/functional/pattern_matching.rb +117 -100
  16. data/lib/functional/protocol.rb +157 -0
  17. data/lib/functional/protocol_info.rb +193 -0
  18. data/lib/functional/record.rb +155 -0
  19. data/lib/functional/type_check.rb +112 -0
  20. data/lib/functional/union.rb +152 -0
  21. data/lib/functional/version.rb +3 -1
  22. data/spec/functional/abstract_struct_shared.rb +154 -0
  23. data/spec/functional/complex_pattern_matching_spec.rb +205 -0
  24. data/spec/functional/configuration_spec.rb +17 -0
  25. data/spec/functional/delay_spec.rb +147 -0
  26. data/spec/functional/either_spec.rb +237 -0
  27. data/spec/functional/memo_spec.rb +207 -0
  28. data/spec/functional/option_spec.rb +292 -0
  29. data/spec/functional/pattern_matching_spec.rb +279 -276
  30. data/spec/functional/protocol_info_spec.rb +444 -0
  31. data/spec/functional/protocol_spec.rb +274 -0
  32. data/spec/functional/record_spec.rb +175 -0
  33. data/spec/functional/type_check_spec.rb +103 -0
  34. data/spec/functional/union_spec.rb +110 -0
  35. data/spec/spec_helper.rb +6 -4
  36. metadata +55 -45
  37. data/lib/functional/behavior.rb +0 -138
  38. data/lib/functional/behaviour.rb +0 -2
  39. data/lib/functional/catalog.rb +0 -487
  40. data/lib/functional/collection.rb +0 -403
  41. data/lib/functional/inflect.rb +0 -127
  42. data/lib/functional/platform.rb +0 -120
  43. data/lib/functional/search.rb +0 -132
  44. data/lib/functional/sort.rb +0 -41
  45. data/lib/functional/utilities.rb +0 -189
  46. data/md/behavior.md +0 -188
  47. data/md/catalog.md +0 -32
  48. data/md/collection.md +0 -32
  49. data/md/inflect.md +0 -32
  50. data/md/pattern_matching.md +0 -512
  51. data/md/platform.md +0 -32
  52. data/md/search.md +0 -32
  53. data/md/sort.md +0 -32
  54. data/md/utilities.md +0 -55
  55. data/spec/functional/behavior_spec.rb +0 -528
  56. data/spec/functional/catalog_spec.rb +0 -1206
  57. data/spec/functional/collection_spec.rb +0 -752
  58. data/spec/functional/inflect_spec.rb +0 -85
  59. data/spec/functional/integration_spec.rb +0 -205
  60. data/spec/functional/platform_spec.rb +0 -501
  61. data/spec/functional/search_spec.rb +0 -187
  62. data/spec/functional/sort_spec.rb +0 -61
  63. data/spec/functional/utilities_spec.rb +0 -277
@@ -0,0 +1,292 @@
1
+ require 'spec_helper'
2
+ require_relative 'abstract_struct_shared'
3
+ require 'securerandom'
4
+
5
+ module Functional
6
+
7
+ describe Option do
8
+
9
+ let!(:value){ 42 }
10
+
11
+ let!(:expected_fields){ [:some] }
12
+ let!(:expected_values){ [value] }
13
+
14
+ let(:struct_class) { Option }
15
+ let(:struct_object) { Option.some(value) }
16
+ let(:other_object) { Option.some(Object.new) }
17
+
18
+ let(:some_subject){ Option.some(value) }
19
+ let(:none_subject){ Option.none }
20
+
21
+ it_should_behave_like :abstract_struct
22
+
23
+ specify{ Functional::Protocol::Satisfy! Option, :Option }
24
+ specify{ Functional::Protocol::Satisfy! Option, :Disposition }
25
+
26
+ let(:some_value){ SecureRandom.uuid }
27
+ let(:other_value){ SecureRandom.uuid }
28
+
29
+ context 'initialization' do
30
+
31
+ it 'cannot be constructed directly' do
32
+ expect {
33
+ Option.new
34
+ }.to raise_error(NameError)
35
+ end
36
+
37
+ it 'sets the value when constructed by #some' do
38
+ expect(Option.some(value).some).to eq value
39
+ end
40
+
41
+ it 'sets the value to nil when constructed by #none' do
42
+ expect(Option.none.some).to be_nil
43
+ end
44
+
45
+ it 'sets the reason to nil when constructed by #none' do
46
+ expect(Option.none.reason).to be_nil
47
+ end
48
+
49
+ it 'sets the optional reason when constructed by #none' do
50
+ reason = 'foobar'
51
+ expect(Option.none(reason).reason).to eq reason
52
+ end
53
+
54
+ it 'freezes the new object' do
55
+ expect(Option.some(:foo)).to be_frozen
56
+ expect(Option.none).to be_frozen
57
+ end
58
+ end
59
+
60
+ context 'state' do
61
+
62
+ specify '#some? returns true when the some value is set' do
63
+ expect(some_subject).to be_some
64
+ end
65
+
66
+ specify '#some? returns false when none' do
67
+ expect(none_subject).to_not be_some
68
+ end
69
+
70
+ specify '#none? returns true when none' do
71
+ expect(none_subject).to be_none
72
+ end
73
+
74
+ specify '#none? returns false when the some value is set' do
75
+ expect(some_subject).to_not be_none
76
+ end
77
+
78
+ specify '#some returns the some value when some is set' do
79
+ expect(some_subject.some).to eq value
80
+ end
81
+
82
+ specify '#some returns nil when none is set' do
83
+ expect(none_subject.some).to be_nil
84
+ end
85
+
86
+ it 'aliases #some? as #fulfilled?' do
87
+ expect(some_subject).to be_fulfilled
88
+ expect(none_subject).to_not be_fulfilled
89
+ end
90
+
91
+ it 'aliases #some? as #value?' do
92
+ expect(some_subject).to be_value
93
+ expect(none_subject).to_not be_value
94
+ end
95
+
96
+ it 'aliases #none? as #rejected?' do
97
+ expect(some_subject).to_not be_rejected
98
+ expect(none_subject).to be_rejected
99
+ end
100
+
101
+ it 'aliases #none? as #reason?' do
102
+ expect(some_subject).to_not be_reason
103
+ expect(none_subject).to be_reason
104
+ end
105
+
106
+ it 'aliases #some as #value' do
107
+ expect(some_subject.value).to eq value
108
+ expect(none_subject.value).to be_nil
109
+ end
110
+
111
+ specify '#reason returns nil when some' do
112
+ expect(some_subject.reason).to be_nil
113
+ end
114
+ end
115
+
116
+ context 'length' do
117
+
118
+ it 'returns 1 when some' do
119
+ expect(Option.some(:foo).length).to eq 1
120
+ end
121
+
122
+ it 'returns 0 when none' do
123
+ expect(Option.none.length).to eq 0
124
+ end
125
+
126
+ it 'as aliased as #size' do
127
+ expect(Option.some(:foo).size).to eq 1
128
+ expect(Option.none.size).to eq 0
129
+ end
130
+ end
131
+
132
+ context '#and' do
133
+
134
+ it 'returns false when none' do
135
+ expect(Option.none.and(true)).to be false
136
+ end
137
+
138
+ it 'returns true when some and other is a some Option' do
139
+ other = Option.some(42)
140
+ expect(Option.some(:foo).and(other)).to be true
141
+ end
142
+
143
+ it 'returns false when some and other is a none Option' do
144
+ other = Option.none
145
+ expect(Option.some(:foo).and(other)).to be false
146
+ end
147
+
148
+ it 'passes the value to the given block when some' do
149
+ expected = false
150
+ other = ->(some){ expected = some }
151
+ Option.some(42).and(&other)
152
+ expect(expected).to eq 42
153
+ end
154
+
155
+ it 'returns true when some and the block returns a truthy value' do
156
+ other = ->(some){ 'truthy' }
157
+ expect(Option.some(42).and(&other)).to be true
158
+ end
159
+
160
+ it 'returns false when some and the block returns a falsey value' do
161
+ other = ->(some){ nil }
162
+ expect(Option.some(42).and(&other)).to be false
163
+ end
164
+
165
+ it 'returns true when some and given a truthy value' do
166
+ expect(Option.some(42).and('truthy')).to be true
167
+ end
168
+
169
+ it 'returns false when some and given a falsey value' do
170
+ expect(Option.some(42).and(nil)).to be false
171
+ end
172
+
173
+ it 'raises an exception when given both a value and a block' do
174
+ expect {
175
+ Option.some(42).and(:foo){|some| :bar }
176
+ }.to raise_error(ArgumentError)
177
+ end
178
+ end
179
+
180
+ context '#or' do
181
+
182
+ it 'returns true when some' do
183
+ expect(Option.some(42).or(nil)).to be true
184
+ end
185
+
186
+ it 'returns true when none and other is a some Option' do
187
+ other = Option.some(42)
188
+ expect(Option.none.or(other)).to be true
189
+ end
190
+
191
+ it 'returns false when none and other is a none Option' do
192
+ other = Option.none
193
+ expect(Option.none.or(other)).to be false
194
+ end
195
+
196
+ it 'returns true when none and the block returns a truthy value' do
197
+ other = ->{ 42 }
198
+ expect(Option.none.or(&other)).to be true
199
+ end
200
+
201
+ it 'returns false when none and the block returns a falsey value' do
202
+ other = ->{ false }
203
+ expect(Option.none.or(&other)).to be false
204
+ end
205
+
206
+ it 'returns true when none and given a truthy value' do
207
+ expect(Option.none.or('truthy')).to be true
208
+ end
209
+
210
+ it 'returns false when none and given a falsey value' do
211
+ expect(Option.none.or(nil)).to be false
212
+ end
213
+
214
+ it 'raises an exception when given both a value and a block' do
215
+ expect {
216
+ Option.none.and(:foo){ :bar }
217
+ }.to raise_error(ArgumentError)
218
+ end
219
+ end
220
+
221
+ context '#else' do
222
+
223
+ it 'returns the value when some' do
224
+ expect(Option.some(some_value).else(other_value)).to eq some_value
225
+ end
226
+
227
+ it 'returns the given value when none' do
228
+ expect(Option.none.else(other_value)).to eq other_value
229
+ end
230
+
231
+ it 'returns the other value when none and given a some Option' do
232
+ other = Option.some(other_value)
233
+ expect(Option.none.else(other)).to eq other_value
234
+ end
235
+
236
+ it 'returns nil when none and given a none Option' do
237
+ other = Option.none
238
+ expect(Option.none.else(other)).to be_nil
239
+ end
240
+
241
+ it 'returns the result of the given block when none' do
242
+ other = ->{ other_value }
243
+ expect(Option.none.else(&other)).to eq other_value
244
+ end
245
+
246
+ it 'raises an exception when given both a value and a block' do
247
+ expect {
248
+ Option.none.else(:foo){ :bar }
249
+ }.to raise_error(ArgumentError)
250
+ end
251
+ end
252
+
253
+ context '#iff' do
254
+
255
+ it 'returns a some option with the given value when the boolean is true' do
256
+ subject = Option.iff(:foo, true)
257
+ expect(subject).to be_some
258
+ expect(subject.some).to eq :foo
259
+ end
260
+
261
+ it 'returns a none option when the boolean is false' do
262
+ subject = Option.iff(:foo, false)
263
+ expect(subject).to be_none
264
+ expect(subject.some).to be_nil
265
+ end
266
+
267
+ it 'returns a some option with the given value when the block is truthy' do
268
+ subject = Option.iff(:foo){ :baz }
269
+ expect(subject).to be_some
270
+ expect(subject.some).to eq :foo
271
+ end
272
+
273
+ it 'returns a none option when the block is false' do
274
+ subject = Option.iff(:foo){ false }
275
+ expect(subject).to be_none
276
+ expect(subject.some).to be_nil
277
+ end
278
+
279
+ it 'returns a none option when the block is nil' do
280
+ subject = Option.iff(:foo){ nil }
281
+ expect(subject).to be_none
282
+ expect(subject.some).to be_nil
283
+ end
284
+
285
+ it 'raises an exception when both a boolean and a block are given' do
286
+ expect {
287
+ subject = Option.iff(:foo, true){ nil }
288
+ }.to raise_error(ArgumentError)
289
+ end
290
+ end
291
+ end
292
+ end
@@ -1,416 +1,419 @@
1
1
  require 'spec_helper'
2
2
  require 'ostruct'
3
3
 
4
- describe PatternMatching do
4
+ module Functional
5
5
 
6
- def new_clazz(&block)
7
- clazz = Class.new
8
- clazz.send(:include, PatternMatching)
9
- clazz.instance_eval(&block) if block_given?
10
- return clazz
11
- end
6
+ describe PatternMatching do
12
7
 
13
- subject { new_clazz }
8
+ def new_clazz(&block)
9
+ clazz = Class.new
10
+ clazz.send(:include, PatternMatching)
11
+ clazz.instance_eval(&block) if block_given?
12
+ return clazz
13
+ end
14
14
 
15
- context '#defn declaration' do
15
+ subject { new_clazz }
16
16
 
17
- it 'can be used within a class declaration' do
18
- lambda {
19
- class Clazz
20
- include PatternMatching
21
- defn(:foo){}
22
- end
23
- }.should_not raise_error
24
- end
17
+ context '#defn declaration' do
25
18
 
26
- it 'can be used on a class object' do
27
- lambda {
28
- clazz = Class.new
29
- clazz.send(:include, PatternMatching)
30
- clazz.defn(:foo){}
31
- }.should_not raise_error
32
- end
19
+ it 'can be used within a class declaration' do
20
+ expect {
21
+ class Clazz
22
+ include PatternMatching
23
+ defn(:foo){}
24
+ end
25
+ }.not_to raise_error
26
+ end
27
+
28
+ it 'can be used on a class object' do
29
+ expect {
30
+ clazz = Class.new
31
+ clazz.send(:include, PatternMatching)
32
+ clazz.defn(:foo){}
33
+ }.not_to raise_error
34
+ end
33
35
 
34
- it 'requires a block' do
35
- lambda {
36
- clazz = Class.new
37
- clazz.send(:include, PatternMatching)
38
- clazz.defn(:foo)
39
- }.should raise_error(ArgumentError)
36
+ it 'requires a block' do
37
+ expect {
38
+ clazz = Class.new
39
+ clazz.send(:include, PatternMatching)
40
+ clazz.defn(:foo)
41
+ }.to raise_error(ArgumentError)
42
+ end
40
43
  end
41
- end
42
44
 
43
- context 'constructor' do
45
+ context 'constructor' do
44
46
 
45
- it 'can pattern match the constructor' do
47
+ it 'can pattern match the constructor' do
46
48
 
47
- unless RUBY_VERSION == '1.9.2'
48
- subject.defn(:initialize, PatternMatching::UNBOUND, PatternMatching::UNBOUND, PatternMatching::UNBOUND) { 'three args' }
49
- subject.defn(:initialize, PatternMatching::UNBOUND, PatternMatching::UNBOUND) { 'two args' }
50
- subject.defn(:initialize, PatternMatching::UNBOUND) { 'one arg' }
49
+ unless RUBY_VERSION == '1.9.2'
50
+ subject.defn(:initialize, PatternMatching::UNBOUND, PatternMatching::UNBOUND, PatternMatching::UNBOUND) { 'three args' }
51
+ subject.defn(:initialize, PatternMatching::UNBOUND, PatternMatching::UNBOUND) { 'two args' }
52
+ subject.defn(:initialize, PatternMatching::UNBOUND) { 'one arg' }
51
53
 
52
- lambda { subject.new(1) }.should_not raise_error
53
- lambda { subject.new(1, 2) }.should_not raise_error
54
- lambda { subject.new(1, 2, 3) }.should_not raise_error
55
- lambda { subject.new(1, 2, 3, 4) }.should raise_error
54
+ expect { subject.new(1) }.not_to raise_error
55
+ expect { subject.new(1, 2) }.not_to raise_error
56
+ expect { subject.new(1, 2, 3) }.not_to raise_error
57
+ expect { subject.new(1, 2, 3, 4) }.to raise_error
58
+ end
56
59
  end
57
60
  end
58
- end
59
61
 
60
- context 'parameter count' do
62
+ context 'parameter count' do
61
63
 
62
- it 'does not match a call with not enough arguments' do
64
+ it 'does not match a call with not enough arguments' do
63
65
 
64
- subject.defn(:foo, true) { 'expected' }
66
+ subject.defn(:foo, true) { 'expected' }
65
67
 
66
- lambda {
67
- subject.new.foo()
68
- }.should raise_error(NoMethodError)
69
- end
68
+ expect {
69
+ subject.new.foo()
70
+ }.to raise_error(NoMethodError)
71
+ end
70
72
 
71
- it 'does not match a call with too many arguments' do
73
+ it 'does not match a call with too many arguments' do
72
74
 
73
- subject.defn(:foo, true) { 'expected' }
75
+ subject.defn(:foo, true) { 'expected' }
76
+
77
+ expect {
78
+ subject.new.foo(true, false)
79
+ }.to raise_error(NoMethodError)
80
+ end
74
81
 
75
- lambda {
76
- subject.new.foo(true, false)
77
- }.should raise_error(NoMethodError)
78
82
  end
79
83
 
80
- end
84
+ context 'recursion' do
81
85
 
82
- context 'recursion' do
86
+ it 'defers unmatched calls to the superclass' do
83
87
 
84
- it 'defers unmatched calls to the superclass' do
88
+ class UnmatchedCallTesterSuperclass
89
+ def foo(bar)
90
+ return bar
91
+ end
92
+ end
85
93
 
86
- class UnmatchedCallTesterSuperclass
87
- def foo(bar)
88
- return bar
94
+ class UnmatchedCallTesterSubclass < UnmatchedCallTesterSuperclass
95
+ include PatternMatching
96
+ defn(:foo) { 'baz' }
89
97
  end
90
- end
91
98
 
92
- class UnmatchedCallTesterSubclass < UnmatchedCallTesterSuperclass
93
- include PatternMatching
94
- defn(:foo) { 'baz' }
99
+ subject = UnmatchedCallTesterSubclass.new
100
+ expect(subject.foo(:bar)).to eq :bar
95
101
  end
96
102
 
97
- subject = UnmatchedCallTesterSubclass.new
98
- subject.foo(:bar).should eq :bar
99
- end
103
+ it 'can call another match from within a match' do
100
104
 
101
- it 'can call another match from within a match' do
105
+ subject.defn(:foo, :bar) { |arg| foo(:baz) }
106
+ subject.defn(:foo, :baz) { |arg| 'expected' }
102
107
 
103
- subject.defn(:foo, :bar) { |arg| foo(:baz) }
104
- subject.defn(:foo, :baz) { |arg| 'expected' }
108
+ expect(subject.new.foo(:bar)).to eq 'expected'
109
+ end
105
110
 
106
- subject.new.foo(:bar).should eq 'expected'
107
- end
111
+ it 'can call a superclass method from within a match' do
108
112
 
109
- it 'can call a superclass method from within a match' do
113
+ class RecursiveCallTesterSuperclass
114
+ def foo(bar)
115
+ return bar
116
+ end
117
+ end
110
118
 
111
- class RecursiveCallTesterSuperclass
112
- def foo(bar)
113
- return bar
119
+ class RecursiveCallTesterSubclass < RecursiveCallTesterSuperclass
120
+ include PatternMatching
121
+ defn(:foo, :bar) { foo(:baz) }
114
122
  end
115
- end
116
123
 
117
- class RecursiveCallTesterSubclass < RecursiveCallTesterSuperclass
118
- include PatternMatching
119
- defn(:foo, :bar) { foo(:baz) }
124
+ subject = RecursiveCallTesterSubclass.new
125
+ expect(subject.foo(:bar)).to eq :baz
120
126
  end
121
-
122
- subject = RecursiveCallTesterSubclass.new
123
- subject.foo(:bar).should eq :baz
124
127
  end
125
- end
126
128
 
127
- context 'datatypes' do
129
+ context 'datatypes' do
128
130
 
129
- it 'matches an argument of the class given in the match parameter' do
131
+ it 'matches an argument of the class given in the match parameter' do
130
132
 
131
- subject.defn(:foo, Integer) { 'expected' }
132
- subject.new.foo(100).should eq 'expected'
133
+ subject.defn(:foo, Integer) { 'expected' }
134
+ expect(subject.new.foo(100)).to eq 'expected'
133
135
 
134
- lambda {
135
- subject.new.foo('hello')
136
- }.should raise_error(NoMethodError)
137
- end
136
+ expect {
137
+ subject.new.foo('hello')
138
+ }.to raise_error(NoMethodError)
139
+ end
138
140
 
139
- it 'passes the matched argument to the block' do
141
+ it 'passes the matched argument to the block' do
140
142
 
141
- subject.defn(:foo, Integer) { |arg| arg }
142
- subject.new.foo(100).should eq 100
143
+ subject.defn(:foo, Integer) { |arg| arg }
144
+ expect(subject.new.foo(100)).to eq 100
145
+ end
143
146
  end
144
- end
145
147
 
146
- context 'function with no parameters' do
148
+ context 'function with no parameters' do
147
149
 
148
- it 'accepts no parameters' do
150
+ it 'accepts no parameters' do
149
151
 
150
- subject.defn(:foo){}
151
- obj = subject.new
152
+ subject.defn(:foo){}
153
+ obj = subject.new
152
154
 
153
- lambda {
154
- obj.foo
155
- }.should_not raise_error
156
- end
155
+ expect {
156
+ obj.foo
157
+ }.not_to raise_error
158
+ end
157
159
 
158
- it 'does not accept any parameters' do
160
+ it 'does not accept any parameters' do
159
161
 
160
- subject.defn(:foo){}
161
- obj = subject.new
162
+ subject.defn(:foo){}
163
+ obj = subject.new
162
164
 
163
- lambda {
164
- obj.foo(1)
165
- }.should raise_error(NoMethodError)
166
- end
165
+ expect {
166
+ obj.foo(1)
167
+ }.to raise_error(NoMethodError)
168
+ end
167
169
 
168
- it 'returns the correct value' do
169
- subject.defn(:foo){ true }
170
- subject.new.foo.should be_true
170
+ it 'returns the correct value' do
171
+ subject.defn(:foo){ true }
172
+ expect(subject.new.foo).to be true
173
+ end
171
174
  end
172
- end
173
175
 
174
- context 'function with one parameter' do
176
+ context 'function with one parameter' do
175
177
 
176
- it 'matches a nil parameter' do
178
+ it 'matches a nil parameter' do
177
179
 
178
- subject.defn(:foo, nil) { 'expected' }
179
- subject.new.foo(nil).should eq 'expected'
180
+ subject.defn(:foo, nil) { 'expected' }
181
+ expect(subject.new.foo(nil)).to eq 'expected'
180
182
 
181
- lambda {
182
- subject.new.foo('no match should be found')
183
- }.should raise_error(NoMethodError)
184
- end
183
+ expect {
184
+ subject.new.foo('no match should be found')
185
+ }.to raise_error(NoMethodError)
186
+ end
185
187
 
186
- it 'matches a boolean parameter' do
188
+ it 'matches a boolean parameter' do
187
189
 
188
- subject.defn(:foo, true) { 'expected' }
189
- subject.defn(:foo, false) { 'false case' }
190
+ subject.defn(:foo, true) { 'expected' }
191
+ subject.defn(:foo, false) { 'false case' }
190
192
 
191
- subject.new.foo(true).should eq 'expected'
192
- subject.new.foo(false).should eq 'false case'
193
+ expect(subject.new.foo(true)).to eq 'expected'
194
+ expect(subject.new.foo(false)).to eq 'false case'
193
195
 
194
- lambda {
195
- subject.new.foo('no match should be found')
196
- }.should raise_error(NoMethodError)
197
- end
196
+ expect {
197
+ subject.new.foo('no match should be found')
198
+ }.to raise_error(NoMethodError)
199
+ end
198
200
 
199
- it 'matches a symbol parameter' do
201
+ it 'matches a symbol parameter' do
200
202
 
201
- subject.defn(:foo, :bar) { 'expected' }
202
- subject.new.foo(:bar).should eq 'expected'
203
+ subject.defn(:foo, :bar) { 'expected' }
204
+ expect(subject.new.foo(:bar)).to eq 'expected'
203
205
 
204
- lambda {
205
- subject.new.foo(:baz)
206
- }.should raise_error(NoMethodError)
207
- end
206
+ expect {
207
+ subject.new.foo(:baz)
208
+ }.to raise_error(NoMethodError)
209
+ end
208
210
 
209
- it 'matches a number parameter' do
211
+ it 'matches a number parameter' do
210
212
 
211
- subject.defn(:foo, 10) { 'expected' }
212
- subject.new.foo(10).should eq 'expected'
213
+ subject.defn(:foo, 10) { 'expected' }
214
+ expect(subject.new.foo(10)).to eq 'expected'
213
215
 
214
- lambda {
215
- subject.new.foo(11.0)
216
- }.should raise_error(NoMethodError)
217
- end
216
+ expect {
217
+ subject.new.foo(11.0)
218
+ }.to raise_error(NoMethodError)
219
+ end
218
220
 
219
- it 'matches a string parameter' do
221
+ it 'matches a string parameter' do
220
222
 
221
- subject.defn(:foo, 'bar') { 'expected' }
222
- subject.new.foo('bar').should eq 'expected'
223
+ subject.defn(:foo, 'bar') { 'expected' }
224
+ expect(subject.new.foo('bar')).to eq 'expected'
223
225
 
224
- lambda {
225
- subject.new.foo('baz')
226
- }.should raise_error(NoMethodError)
227
- end
226
+ expect {
227
+ subject.new.foo('baz')
228
+ }.to raise_error(NoMethodError)
229
+ end
228
230
 
229
- it 'matches an array parameter' do
231
+ it 'matches an array parameter' do
230
232
 
231
- subject.defn(:foo, [1, 2, 3]) { 'expected' }
232
- subject.new.foo([1, 2, 3]).should eq 'expected'
233
+ subject.defn(:foo, [1, 2, 3]) { 'expected' }
234
+ expect(subject.new.foo([1, 2, 3])).to eq 'expected'
233
235
 
234
- lambda {
235
- subject.new.foo([3, 4, 5])
236
- }.should raise_error(NoMethodError)
237
- end
236
+ expect {
237
+ subject.new.foo([3, 4, 5])
238
+ }.to raise_error(NoMethodError)
239
+ end
238
240
 
239
- it 'matches a hash parameter' do
241
+ it 'matches a hash parameter' do
240
242
 
241
- subject.defn(:foo, bar: 1, baz: 2) { 'expected' }
242
- subject.new.foo(bar: 1, baz: 2).should eq 'expected'
243
+ subject.defn(:foo, bar: 1, baz: 2) { 'expected' }
244
+ expect(subject.new.foo(bar: 1, baz: 2)).to eq 'expected'
243
245
 
244
- lambda {
245
- subject.new.foo(foo: 0, bar: 1)
246
- }.should raise_error(NoMethodError)
247
- end
246
+ expect {
247
+ subject.new.foo(foo: 0, bar: 1)
248
+ }.to raise_error(NoMethodError)
249
+ end
248
250
 
249
- it 'matches an object parameter' do
251
+ it 'matches an object parameter' do
250
252
 
251
- subject.defn(:foo, OpenStruct.new(foo: :bar)) { 'expected' }
252
- subject.new.foo(OpenStruct.new(foo: :bar)).should eq 'expected'
253
+ subject.defn(:foo, OpenStruct.new(foo: :bar)) { 'expected' }
254
+ expect(subject.new.foo(OpenStruct.new(foo: :bar))).to eq 'expected'
253
255
 
254
- lambda {
255
- subject.new.foo(OpenStruct.new(bar: :baz))
256
- }.should raise_error(NoMethodError)
257
- end
256
+ expect {
257
+ subject.new.foo(OpenStruct.new(bar: :baz))
258
+ }.to raise_error(NoMethodError)
259
+ end
258
260
 
259
- it 'matches an unbound parameter' do
261
+ it 'matches an unbound parameter' do
260
262
 
261
- subject.defn(:foo, PatternMatching::UNBOUND) {|arg| arg }
262
- subject.new.foo(:foo).should eq :foo
263
+ subject.defn(:foo, PatternMatching::UNBOUND) {|arg| arg }
264
+ expect(subject.new.foo(:foo)).to eq :foo
265
+ end
263
266
  end
264
- end
265
267
 
266
- context 'function with two parameters' do
268
+ context 'function with two parameters' do
267
269
 
268
- it 'matches two bound arguments' do
270
+ it 'matches two bound arguments' do
269
271
 
270
- subject.defn(:foo, :male, :female){ 'expected' }
271
- subject.new.foo(:male, :female).should eq 'expected'
272
+ subject.defn(:foo, :male, :female){ 'expected' }
273
+ expect(subject.new.foo(:male, :female)).to eq 'expected'
272
274
 
273
- lambda {
274
- subject.new.foo(1, 2)
275
- }.should raise_error(NoMethodError)
276
- end
275
+ expect {
276
+ subject.new.foo(1, 2)
277
+ }.to raise_error(NoMethodError)
278
+ end
277
279
 
278
- it 'matches two unbound arguments' do
280
+ it 'matches two unbound arguments' do
279
281
 
280
- subject.defn(:foo, PatternMatching::UNBOUND, PatternMatching::UNBOUND) do |first, second|
281
- [first, second]
282
+ subject.defn(:foo, PatternMatching::UNBOUND, PatternMatching::UNBOUND) do |first, second|
283
+ [first, second]
284
+ end
285
+ expect(subject.new.foo(:male, :female)).to eq [:male, :female]
282
286
  end
283
- subject.new.foo(:male, :female).should eq [:male, :female]
284
- end
285
287
 
286
- it 'matches when the first argument is bound and the second is not' do
288
+ it 'matches when the first argument is bound and the second is not' do
287
289
 
288
- subject.defn(:foo, :male, PatternMatching::UNBOUND) do |second|
289
- second
290
+ subject.defn(:foo, :male, PatternMatching::UNBOUND) do |second|
291
+ second
292
+ end
293
+ expect(subject.new.foo(:male, :female)).to eq :female
290
294
  end
291
- subject.new.foo(:male, :female).should eq :female
292
- end
293
295
 
294
- it 'matches when the second argument is bound and the first is not' do
296
+ it 'matches when the second argument is bound and the first is not' do
295
297
 
296
- subject.defn(:foo, PatternMatching::UNBOUND, :female) do |first|
297
- first
298
+ subject.defn(:foo, PatternMatching::UNBOUND, :female) do |first|
299
+ first
300
+ end
301
+ expect(subject.new.foo(:male, :female)).to eq :male
298
302
  end
299
- subject.new.foo(:male, :female).should eq :male
300
303
  end
301
- end
302
304
 
303
- context 'functions with hash arguments' do
305
+ context 'functions with hash arguments' do
304
306
 
305
- it 'matches an empty argument hash with an empty parameter hash' do
307
+ it 'matches an empty argument hash with an empty parameter hash' do
306
308
 
307
- subject.defn(:foo, {}) { true }
308
- subject.new.foo({}).should be_true
309
+ subject.defn(:foo, {}) { true }
310
+ expect(subject.new.foo({})).to be true
309
311
 
310
- lambda {
311
- subject.new.foo({one: :two})
312
- }.should raise_error(NoMethodError)
313
- end
312
+ expect {
313
+ subject.new.foo({one: :two})
314
+ }.to raise_error(NoMethodError)
315
+ end
314
316
 
315
- it 'matches when all hash keys and values match' do
317
+ it 'matches when all hash keys and values match' do
316
318
 
317
- subject.defn(:foo, {bar: :baz}) { true }
318
- subject.new.foo(bar: :baz).should be_true
319
+ subject.defn(:foo, {bar: :baz}) { true }
320
+ expect(subject.new.foo(bar: :baz)).to be true
319
321
 
320
- lambda {
321
- subject.new.foo({one: :two})
322
- }.should raise_error(NoMethodError)
323
- end
322
+ expect {
323
+ subject.new.foo({one: :two})
324
+ }.to raise_error(NoMethodError)
325
+ end
324
326
 
325
- it 'matches when every pattern key/value are in the argument' do
327
+ it 'matches when every pattern key/value are in the argument' do
326
328
 
327
- subject.defn(:foo, {bar: :baz}) { true }
328
- subject.new.foo(foo: :bar, bar: :baz).should be_true
329
- end
329
+ subject.defn(:foo, {bar: :baz}) { true }
330
+ expect(subject.new.foo(foo: :bar, bar: :baz)).to be true
331
+ end
330
332
 
331
- it 'matches when all keys with unbound values in the pattern have an argument' do
333
+ it 'matches when all keys with unbound values in the pattern have an argument' do
332
334
 
333
- subject.defn(:foo, {bar: PatternMatching::UNBOUND}) { true }
334
- subject.new.foo(bar: :baz).should be_true
335
- end
335
+ subject.defn(:foo, {bar: PatternMatching::UNBOUND}) { true }
336
+ expect(subject.new.foo(bar: :baz)).to be true
337
+ end
336
338
 
337
- it 'passes unbound values to the block' do
339
+ it 'passes unbound values to the block' do
338
340
 
339
- subject.defn(:foo, {bar: PatternMatching::UNBOUND}) {|arg| arg }
340
- subject.new.foo(bar: :baz).should eq :baz
341
- end
341
+ subject.defn(:foo, {bar: PatternMatching::UNBOUND}) {|arg| arg }
342
+ expect(subject.new.foo(bar: :baz)).to eq :baz
343
+ end
342
344
 
343
- it 'passes the matched hash to the block' do
345
+ it 'passes the matched hash to the block' do
344
346
 
345
- subject.defn(:foo, {bar: :baz}) { |opts| opts }
346
- subject.new.foo(bar: :baz).should == {bar: :baz}
347
- end
347
+ subject.defn(:foo, {bar: :baz}) { |opts| opts }
348
+ expect(subject.new.foo(bar: :baz)).to eq({bar: :baz})
349
+ end
348
350
 
349
- it 'does not match a non-hash argument' do
351
+ it 'does not match a non-hash argument' do
350
352
 
351
- subject.defn(:foo, {}) { true }
353
+ subject.defn(:foo, {}) { true }
352
354
 
353
- lambda {
354
- subject.new.foo(:bar)
355
- }.should raise_error(NoMethodError)
356
- end
355
+ expect {
356
+ subject.new.foo(:bar)
357
+ }.to raise_error(NoMethodError)
358
+ end
357
359
 
358
- it 'supports idiomatic has-as-last-argument syntax' do
360
+ it 'supports idiomatic has-as-last-argument syntax' do
359
361
 
360
- subject.defn(:foo, PatternMatching::UNBOUND) { |opts| opts }
361
- subject.new.foo(bar: :baz, one: 1, many: 2).should == {bar: :baz, one: 1, many: 2}
362
+ subject.defn(:foo, PatternMatching::UNBOUND) { |opts| opts }
363
+ expect(subject.new.foo(bar: :baz, one: 1, many: 2)).to eq({bar: :baz, one: 1, many: 2})
364
+ end
362
365
  end
363
- end
364
366
 
365
- context 'varaible-length argument lists' do
367
+ context 'varaible-length argument lists' do
368
+
369
+ it 'supports ALL as the last parameter' do
366
370
 
367
- it 'supports ALL as the last parameter' do
368
-
369
- subject.defn(:foo, 1, 2, PatternMatching::ALL) { |args| args }
370
- subject.new.foo(1, 2, 3).should == [3]
371
- subject.new.foo(1, 2, :foo, :bar).should == [:foo, :bar]
372
- subject.new.foo(1, 2, :foo, :bar, one: 1, two: 2).should == [:foo, :bar, {one: 1, two: 2}]
371
+ subject.defn(:foo, 1, 2, PatternMatching::ALL) { |args| args }
372
+ expect(subject.new.foo(1, 2, 3)).to eq([3])
373
+ expect(subject.new.foo(1, 2, :foo, :bar)).to eq([:foo, :bar])
374
+ expect(subject.new.foo(1, 2, :foo, :bar, one: 1, two: 2)).to eq([:foo, :bar, {one: 1, two: 2}])
375
+ end
373
376
  end
374
- end
375
377
 
376
- context 'guard clauses' do
378
+ context 'guard clauses' do
377
379
 
378
- it 'matches when the guard clause returns true' do
380
+ it 'matches when the guard clause returns true' do
379
381
 
380
- subject.defn(:old_enough, PatternMatching::UNBOUND){
381
- true
382
- }.when{|x| x > 16 }
382
+ subject.defn(:old_enough, PatternMatching::UNBOUND){
383
+ true
384
+ }.when{|x| x > 16 }
383
385
 
384
- subject.new.old_enough(20).should be_true
385
- end
386
+ expect(subject.new.old_enough(20)).to be true
387
+ end
386
388
 
387
- it 'does not match when the guard clause returns false' do
389
+ it 'does not match when the guard clause returns false' do
388
390
 
389
- subject.defn(:old_enough, PatternMatching::UNBOUND){
390
- true
391
- }.when{|x| x > 16 }
391
+ subject.defn(:old_enough, PatternMatching::UNBOUND){
392
+ true
393
+ }.when{|x| x > 16 }
392
394
 
393
- lambda {
394
- subject.new.old_enough(10)
395
- }.should raise_error(NoMethodError)
396
- end
395
+ expect {
396
+ subject.new.old_enough(10)
397
+ }.to raise_error(NoMethodError)
398
+ end
397
399
 
398
- it 'continues pattern matching when the guard clause returns false' do
400
+ it 'continues pattern matching when the guard clause returns false' do
399
401
 
400
- subject.defn(:old_enough, PatternMatching::UNBOUND){
401
- true
402
- }.when{|x| x > 16 }
402
+ subject.defn(:old_enough, PatternMatching::UNBOUND){
403
+ true
404
+ }.when{|x| x > 16 }
403
405
 
404
- subject.defn(:old_enough, PatternMatching::UNBOUND) { false }
406
+ subject.defn(:old_enough, PatternMatching::UNBOUND) { false }
405
407
 
406
- subject.new.old_enough(10).should be_false
407
- end
408
+ expect(subject.new.old_enough(10)).to be false
409
+ end
408
410
 
409
- it 'raises an exception when the guard clause does not have a block' do
411
+ it 'raises an exception when the guard clause does not have a block' do
410
412
 
411
- lambda {
412
- subject.defn(:foo).when
413
- }.should raise_error(ArgumentError)
413
+ expect {
414
+ subject.defn(:initialize, PatternMatching::UNBOUND) { 'one arg' }.when
415
+ }.to raise_error(ArgumentError)
416
+ end
414
417
  end
415
418
  end
416
419
  end