functional-ruby 0.7.7 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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