matchmaker 0.0.1
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.
- data/.document +5 -0
- data/.gitignore +5 -0
- data/LICENSE +20 -0
- data/README +310 -0
- data/README.markdown +310 -0
- data/Rakefile +48 -0
- data/VERSION +1 -0
- data/lib/matchmaker.rb +479 -0
- data/matchmaker.gemspec +55 -0
- data/spec/case_spec.rb +466 -0
- data/spec/spec_helper.rb +9 -0
- metadata +77 -0
data/matchmaker.gemspec
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Generated by jeweler
|
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
|
4
|
+
# -*- encoding: utf-8 -*-
|
|
5
|
+
|
|
6
|
+
Gem::Specification.new do |s|
|
|
7
|
+
s.name = %q{matchmaker}
|
|
8
|
+
s.version = "0.0.1"
|
|
9
|
+
|
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
|
11
|
+
s.authors = ["Howard Yeh"]
|
|
12
|
+
s.date = %q{2009-11-30}
|
|
13
|
+
s.description = %q{A pattern matching library}
|
|
14
|
+
s.email = %q{hayeah@gmail.com}
|
|
15
|
+
s.extra_rdoc_files = [
|
|
16
|
+
"LICENSE",
|
|
17
|
+
"README",
|
|
18
|
+
"README.markdown"
|
|
19
|
+
]
|
|
20
|
+
s.files = [
|
|
21
|
+
".document",
|
|
22
|
+
".gitignore",
|
|
23
|
+
"LICENSE",
|
|
24
|
+
"README.markdown",
|
|
25
|
+
"Rakefile",
|
|
26
|
+
"VERSION",
|
|
27
|
+
"lib/matchmaker.rb",
|
|
28
|
+
"matchmaker.gemspec",
|
|
29
|
+
"spec/case_spec.rb",
|
|
30
|
+
"spec/spec_helper.rb"
|
|
31
|
+
]
|
|
32
|
+
s.homepage = %q{http://github.com/hayeah/case}
|
|
33
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
|
34
|
+
s.require_paths = ["lib"]
|
|
35
|
+
s.rubygems_version = %q{1.3.5}
|
|
36
|
+
s.summary = %q{Ruby Pattern Matching}
|
|
37
|
+
s.test_files = [
|
|
38
|
+
"spec/spec_helper.rb",
|
|
39
|
+
"spec/case_spec.rb"
|
|
40
|
+
]
|
|
41
|
+
|
|
42
|
+
if s.respond_to? :specification_version then
|
|
43
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
|
44
|
+
s.specification_version = 3
|
|
45
|
+
|
|
46
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
|
47
|
+
s.add_development_dependency(%q<rspec>, [">= 0"])
|
|
48
|
+
else
|
|
49
|
+
s.add_dependency(%q<rspec>, [">= 0"])
|
|
50
|
+
end
|
|
51
|
+
else
|
|
52
|
+
s.add_dependency(%q<rspec>, [">= 0"])
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
data/spec/case_spec.rb
ADDED
|
@@ -0,0 +1,466 @@
|
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
|
2
|
+
|
|
3
|
+
describe Case do
|
|
4
|
+
def not_match
|
|
5
|
+
raise_error(Case::CaseFail)
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def be_unbound
|
|
9
|
+
raise_error(Case::UnboundVariable)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
TEST_CONSTANT_1 = :test_constant_1
|
|
13
|
+
it "DSL should preserve module nesting of original block" do
|
|
14
|
+
pending
|
|
15
|
+
Case(1) {
|
|
16
|
+
of(1) { TEST_CONSTANT_1 }
|
|
17
|
+
}.should == TEST_CONSTANT_1
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it "should make a pattern object" do
|
|
21
|
+
pat = Case.pattern {
|
|
22
|
+
[:a,integer,string]
|
|
23
|
+
}
|
|
24
|
+
pat.should be_a(Case::Pattern)
|
|
25
|
+
Case([:a,10,"abc"]) {
|
|
26
|
+
of(pat)
|
|
27
|
+
}.should == true
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it "should pattern match with shortcut" do
|
|
31
|
+
Case("a") {
|
|
32
|
+
of "a"
|
|
33
|
+
}.should == true
|
|
34
|
+
lambda {
|
|
35
|
+
Case("a") {
|
|
36
|
+
of 1
|
|
37
|
+
}
|
|
38
|
+
}.should not_match
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it "should not allow star pattern except in structural patterns" do
|
|
42
|
+
lambda {
|
|
43
|
+
Case.new {
|
|
44
|
+
}
|
|
45
|
+
}.should raise_error
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
it "should not be used with no clauses" do
|
|
49
|
+
lambda { Case.new { } }.should raise_error(Case::NoClauses)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
it "should build case object with clauses" do
|
|
53
|
+
Case.new do
|
|
54
|
+
of 1
|
|
55
|
+
of 2
|
|
56
|
+
end.should be_a(Case)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
it "should build star pattern" do
|
|
60
|
+
star_pattern, literal_pattern = nil
|
|
61
|
+
Case.new {
|
|
62
|
+
literal_pattern = literal(3)
|
|
63
|
+
star_pattern = _!(literal_pattern)
|
|
64
|
+
} rescue Case::NoClauses
|
|
65
|
+
star_pattern.should be_a(Case::StarPattern)
|
|
66
|
+
star_pattern.pattern.should == literal_pattern
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
it "should return true for matched pattern (without action)" do
|
|
70
|
+
c = Case.new do
|
|
71
|
+
of 1
|
|
72
|
+
of :a
|
|
73
|
+
end
|
|
74
|
+
c.match(1).should == true
|
|
75
|
+
lambda { c.match(2) }.should not_match
|
|
76
|
+
c.match(:a).should == true
|
|
77
|
+
lambda { c.match(:b) }.should not_match
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
it "should return value of pattern matched action" do
|
|
81
|
+
c = Case.new do
|
|
82
|
+
of(1) { [1] }
|
|
83
|
+
of(:a) { [:a] }
|
|
84
|
+
of(:b) { throw(:throw_test) }
|
|
85
|
+
end
|
|
86
|
+
c.match(1).should == [1]
|
|
87
|
+
c.match(:a).should == [:a]
|
|
88
|
+
lambda { c.match(:b) }.should throw_symbol(:throw_test)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
it "should throw error for unbound variable" do
|
|
92
|
+
c = Case.new do
|
|
93
|
+
of(literal(1,:a)) { b }
|
|
94
|
+
end
|
|
95
|
+
lambda { c.match(1) }.should be_unbound
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
it "should create binding for matched variable" do
|
|
99
|
+
c = Case.new do
|
|
100
|
+
of(literal(1,:a)) { a }
|
|
101
|
+
end
|
|
102
|
+
c.match(1).should == 1
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
it "should scope bindings"
|
|
106
|
+
|
|
107
|
+
it "should downcase symbol for variable binding" do
|
|
108
|
+
c = Case.new do
|
|
109
|
+
of(literal(1,:A)) { a }
|
|
110
|
+
end
|
|
111
|
+
c.match(1).should == 1
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
it "should bind to the same variable iff the values are equal" do
|
|
115
|
+
c = Case.new do
|
|
116
|
+
of([is(1,:a),is(1,:a)])
|
|
117
|
+
of([is(2,:A),is(1,:A)])
|
|
118
|
+
of([is(3,:B),is(3,:b)])
|
|
119
|
+
end
|
|
120
|
+
c.match([1,1]).should == true
|
|
121
|
+
lambda { c.match([2,1]) }.should not_match
|
|
122
|
+
c.match([3,3]).should == true
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
describe "guard" do
|
|
126
|
+
it "should add guard with the Pattern#when" do
|
|
127
|
+
c = Case.new do
|
|
128
|
+
of(literal(1).when{|o| false})
|
|
129
|
+
of(literal(2))
|
|
130
|
+
end
|
|
131
|
+
lambda { c.match(1) }.should not_match
|
|
132
|
+
c.match(2).should == true
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
it "should fail pattern if guard fails" do
|
|
136
|
+
c = Case.new do
|
|
137
|
+
of(literal(1){|o| false})
|
|
138
|
+
of(literal(2))
|
|
139
|
+
end
|
|
140
|
+
lambda { c.match(1) }.should not_match
|
|
141
|
+
c.match(2).should == true
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
describe "literal pattern" do
|
|
146
|
+
it "should match literal by object equality" do
|
|
147
|
+
o1 = Object.new
|
|
148
|
+
o2 = Object.new
|
|
149
|
+
c = Case.new do
|
|
150
|
+
of o1
|
|
151
|
+
end
|
|
152
|
+
c.match(o1).should == true
|
|
153
|
+
lambda { c.match(o2) }.should not_match
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
describe "class pattern" do
|
|
158
|
+
it "should match objects of a class" do
|
|
159
|
+
s1 = "a"
|
|
160
|
+
s2 = "b"
|
|
161
|
+
c = Case.new do
|
|
162
|
+
of(a(String))
|
|
163
|
+
end
|
|
164
|
+
c.match(s1).should == true
|
|
165
|
+
c.match(s2).should == true
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
it "should use guard" do
|
|
169
|
+
c = Case.new do
|
|
170
|
+
of(a(Integer))
|
|
171
|
+
of(a(String) { false })
|
|
172
|
+
end
|
|
173
|
+
c.match(1).should == true
|
|
174
|
+
lambda { c.match("a") }.should not_match
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
describe "integer pattern" do
|
|
179
|
+
it "should match a range" do
|
|
180
|
+
c = Case.new do
|
|
181
|
+
of(integer(1..100){ |i| i % 2 == 0})
|
|
182
|
+
end
|
|
183
|
+
c.match(2).should == true
|
|
184
|
+
c.match(100).should == true
|
|
185
|
+
lambda { c.match(1)}.should not_match
|
|
186
|
+
lambda { c.match(0)}.should not_match
|
|
187
|
+
lambda { c.match(102)}.should not_match
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
it "should match a set" do
|
|
191
|
+
c = Case.new do
|
|
192
|
+
of integer([2,100])
|
|
193
|
+
end
|
|
194
|
+
c.match(2).should == true
|
|
195
|
+
c.match(100).should == true
|
|
196
|
+
lambda { c.match(1)}.should not_match
|
|
197
|
+
lambda { c.match(0)}.should not_match
|
|
198
|
+
lambda { c.match(102)}.should not_match
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
it "should match any integer" do
|
|
202
|
+
c = Case.new do
|
|
203
|
+
of(integer)
|
|
204
|
+
end
|
|
205
|
+
c.match(2).should == true
|
|
206
|
+
c.match(100).should == true
|
|
207
|
+
lambda { c.match(:foo)}.should not_match
|
|
208
|
+
end
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
describe "symbol pattern" do
|
|
212
|
+
it "should match symbol by regexp" do
|
|
213
|
+
c = Case.new do
|
|
214
|
+
of(symbol(/^a.*/))
|
|
215
|
+
end
|
|
216
|
+
c.match(:a).should == true
|
|
217
|
+
c.match(:abc).should == true
|
|
218
|
+
lambda { c.match(:babc) }.should not_match
|
|
219
|
+
lambda { c.match(10) }.should not_match
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
it "should match a symbol by class, string, or symbol" do
|
|
223
|
+
c = Case.new do
|
|
224
|
+
of(symbol { |o| o.to_s.length == 1})
|
|
225
|
+
of(symbol(:ab,:AB)) { ab }
|
|
226
|
+
end
|
|
227
|
+
c.match(:a).should == true
|
|
228
|
+
lambda { c.match(1) }.should not_match
|
|
229
|
+
c.match(:ab).should == :ab
|
|
230
|
+
lambda { c.match(:bc) }.should not_match
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
it "should use guards" do
|
|
234
|
+
c = Case.new do
|
|
235
|
+
of(symbol { |o| false })
|
|
236
|
+
of(symbol(:a) { |o| false })
|
|
237
|
+
of(symbol(/.*/) { |o| false })
|
|
238
|
+
end
|
|
239
|
+
lambda { c.match(:b) }.should not_match
|
|
240
|
+
lambda { c.match(:a) }.should not_match
|
|
241
|
+
lambda { c.match(:faewfe) }.should not_match
|
|
242
|
+
end
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
describe "string pattern" do
|
|
246
|
+
it "should match string by regexp" do
|
|
247
|
+
c = Case.new do
|
|
248
|
+
of(string(/^a.*/))
|
|
249
|
+
end
|
|
250
|
+
c.match("a").should == true
|
|
251
|
+
c.match("abc").should == true
|
|
252
|
+
lambda { c.match("babc") }.should not_match
|
|
253
|
+
lambda { c.match(10) }.should not_match
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
it "should match a string by class, string, or symbol" do
|
|
257
|
+
c = Case.new do
|
|
258
|
+
of(string { |o| o.to_s.length == 1})
|
|
259
|
+
of(string("ab",:AB)) { ab }
|
|
260
|
+
end
|
|
261
|
+
c.match("a").should == true
|
|
262
|
+
lambda { c.match(1) }.should not_match
|
|
263
|
+
lambda { c.match("abc") }.should not_match
|
|
264
|
+
c.match("ab").should == "ab"
|
|
265
|
+
lambda { c.match("bc") }.should not_match
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
it "should use guards" do
|
|
269
|
+
c = Case.new do
|
|
270
|
+
of(string { |o| false })
|
|
271
|
+
of(string("a") { |o| false })
|
|
272
|
+
of(string(/.*/) { |o| false })
|
|
273
|
+
end
|
|
274
|
+
lambda { c.match("a") }.should not_match
|
|
275
|
+
lambda { c.match("abc") }.should not_match
|
|
276
|
+
lambda { c.match("abcde") }.should not_match
|
|
277
|
+
end
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
describe "bind pattern" do
|
|
281
|
+
it "should bind a pattern to a variable" do
|
|
282
|
+
c = Case.new do
|
|
283
|
+
sym = a(Symbol)
|
|
284
|
+
of(bind(sym,:A){|o| o == :foo }) { a }
|
|
285
|
+
of(bind(sym,:A){|o| o == :bar }) { a }
|
|
286
|
+
end
|
|
287
|
+
c.match(:foo).should == :foo
|
|
288
|
+
c.match(:bar).should == :bar
|
|
289
|
+
lambda { c.match(:qux) }.should not_match
|
|
290
|
+
end
|
|
291
|
+
end
|
|
292
|
+
|
|
293
|
+
describe "is pattern" do
|
|
294
|
+
it "should make range a integer range pattern" do
|
|
295
|
+
c = Case.new do
|
|
296
|
+
of(1..100)
|
|
297
|
+
end
|
|
298
|
+
c.match(1).should == true
|
|
299
|
+
c.match(100).should == true
|
|
300
|
+
lambda { c.match(0) }.should not_match
|
|
301
|
+
lambda { c.match(101) }.should not_match
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
it "should make array an array pattern" do
|
|
305
|
+
c = Case.new do
|
|
306
|
+
of([1,2])
|
|
307
|
+
end
|
|
308
|
+
c.match([1,2]).should == true
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
it "should make regexp a string pattern" do
|
|
312
|
+
c = Case.new do
|
|
313
|
+
of(/abc/)
|
|
314
|
+
end
|
|
315
|
+
c.match("0abc0").should == true
|
|
316
|
+
end
|
|
317
|
+
|
|
318
|
+
it "should make hash a hash pattern" do
|
|
319
|
+
c = Case.new do
|
|
320
|
+
of(:a => 1)
|
|
321
|
+
end
|
|
322
|
+
c.match(:a => 1).should == true
|
|
323
|
+
end
|
|
324
|
+
|
|
325
|
+
it "should make class a class pattern" do
|
|
326
|
+
c = Case.new do
|
|
327
|
+
of(String)
|
|
328
|
+
end
|
|
329
|
+
c.match("abc").should == true
|
|
330
|
+
end
|
|
331
|
+
end
|
|
332
|
+
|
|
333
|
+
describe "wildcard pattern" do
|
|
334
|
+
it "should match anything" do
|
|
335
|
+
c = Case.new do
|
|
336
|
+
of(_(:V) { |o| o != :foobarqux }) {
|
|
337
|
+
v
|
|
338
|
+
}
|
|
339
|
+
end
|
|
340
|
+
c.match(10).should == 10
|
|
341
|
+
c.match(:a).should == :a
|
|
342
|
+
c.match("a").should == "a"
|
|
343
|
+
c.match(Object.new).should be_a(Object)
|
|
344
|
+
lambda { c.match(:foobarqux) }.should not_match
|
|
345
|
+
end
|
|
346
|
+
end
|
|
347
|
+
|
|
348
|
+
describe "one_of pattern" do
|
|
349
|
+
it "matches one_of a number of patterns" do
|
|
350
|
+
c = Case.new do
|
|
351
|
+
of(one_of([1,"b"],:V)) {
|
|
352
|
+
v
|
|
353
|
+
}
|
|
354
|
+
end
|
|
355
|
+
c.match(1).should == 1
|
|
356
|
+
c.match("b").should == "b"
|
|
357
|
+
lambda { c.match("c") }.should not_match
|
|
358
|
+
end
|
|
359
|
+
end
|
|
360
|
+
|
|
361
|
+
describe "array pattern" do
|
|
362
|
+
it "should match the exact length of array" do
|
|
363
|
+
c = Case.new {
|
|
364
|
+
of [1,2,3]
|
|
365
|
+
}
|
|
366
|
+
c.match([1,2,3]).should == true
|
|
367
|
+
lambda { c.match([]) }.should not_match
|
|
368
|
+
lambda { c.match([1,2]) }.should not_match
|
|
369
|
+
lambda { c.match([1,2,3,4]) }.should not_match
|
|
370
|
+
end
|
|
371
|
+
|
|
372
|
+
it "should use guard" do
|
|
373
|
+
c = Case.new {
|
|
374
|
+
of(array([1,2,3]){ false })
|
|
375
|
+
}
|
|
376
|
+
lambda { c.match([1,2,3]) }.should not_match
|
|
377
|
+
end
|
|
378
|
+
|
|
379
|
+
it "should match patterns in array pattern" do
|
|
380
|
+
c = Case.new {
|
|
381
|
+
pattern = symbol(/^a.*/)
|
|
382
|
+
of([pattern,pattern,pattern]) { 2 }
|
|
383
|
+
of([]) { 1 }
|
|
384
|
+
}
|
|
385
|
+
c.match([]).should == 1
|
|
386
|
+
c.match([:a,:ab,:abc]).should == 2
|
|
387
|
+
lambda { c.match([:a,:ab,:abc,:abcd]) }.should not_match
|
|
388
|
+
end
|
|
389
|
+
|
|
390
|
+
it "should match tail" do
|
|
391
|
+
c = Case.new {
|
|
392
|
+
of([_!(1)])
|
|
393
|
+
}
|
|
394
|
+
c.match([]).should == true
|
|
395
|
+
c.match([1,1]).should == true
|
|
396
|
+
c.match([1,1,1]).should == true
|
|
397
|
+
c.match([1,1,1,1]).should == true
|
|
398
|
+
end
|
|
399
|
+
|
|
400
|
+
it "should bind tail" do
|
|
401
|
+
c = Case.new {
|
|
402
|
+
of([_!(1,:tail)]) { tail }
|
|
403
|
+
}
|
|
404
|
+
c.match([]).should == []
|
|
405
|
+
c.match([1,1]).should == [1,1]
|
|
406
|
+
end
|
|
407
|
+
|
|
408
|
+
it "should match heads then tail" do
|
|
409
|
+
c = Case.new {
|
|
410
|
+
of([:a,:b,:c,_!(1,:tail)]) { tail }
|
|
411
|
+
}
|
|
412
|
+
c.match([:a,:b,:c]).should == []
|
|
413
|
+
c.match([:a,:b,:c,1]).should == [1]
|
|
414
|
+
c.match([:a,:b,:c,1,1]).should == [1,1]
|
|
415
|
+
lambda { c.match([:a,:b,1,1,1,1,1]) }.should not_match
|
|
416
|
+
lambda { c.match([1,1,1,1,1]) }.should not_match
|
|
417
|
+
lambda { c.match([:a,:b,:c,1,2]) }.should not_match
|
|
418
|
+
end
|
|
419
|
+
|
|
420
|
+
it "should use guard in tail pattern" do
|
|
421
|
+
c = Case.new {
|
|
422
|
+
of [_!(1){ |o| false }]
|
|
423
|
+
of [_!(integer(){ |o| o % 2 == 0 }){ |tail| tail.length == 3 }]
|
|
424
|
+
}
|
|
425
|
+
lambda {c.match([1,1,1])}.should not_match
|
|
426
|
+
lambda {c.match([2,2,1])}.should not_match
|
|
427
|
+
c.match([2,2,2]).should == true
|
|
428
|
+
c.match([2,4,6]).should == true
|
|
429
|
+
lambda {c.match([2,4,6,8])}.should not_match
|
|
430
|
+
end
|
|
431
|
+
|
|
432
|
+
it "should match nested arrays" do
|
|
433
|
+
c = Case.new {
|
|
434
|
+
of [1,2,[3,4,_!(symbol)]]
|
|
435
|
+
}
|
|
436
|
+
c.match([1,2,[3,4,:a,:b,:c]]).should == true
|
|
437
|
+
c.match([1,2,[3,4]]).should == true
|
|
438
|
+
lambda { c.match([1,2,[3,4,5,6,7]]) }.should not_match
|
|
439
|
+
lambda { c.match([1,2,[3]]) }.should not_match
|
|
440
|
+
lambda { c.match([1,2]) }.should not_match
|
|
441
|
+
end
|
|
442
|
+
end
|
|
443
|
+
|
|
444
|
+
describe "hash pattern" do
|
|
445
|
+
it "should match required keys" do
|
|
446
|
+
c = Case.new {
|
|
447
|
+
of(hash(:a => 1, :b => 2))
|
|
448
|
+
}
|
|
449
|
+
c.match(:a => 1, :b => 2).should == true
|
|
450
|
+
c.match(:a => 1, :b => 2, :c => 3).should == true
|
|
451
|
+
lambda { c.match(1) } .should not_match
|
|
452
|
+
lambda { c.match(:a => 1, :b => 3) }.should not_match
|
|
453
|
+
lambda { c.match(:a => 1, :c => 3) }.should not_match
|
|
454
|
+
end
|
|
455
|
+
|
|
456
|
+
it "should match optional keys" do
|
|
457
|
+
c = Case.new {
|
|
458
|
+
of(hash([:a] => 1))
|
|
459
|
+
}
|
|
460
|
+
c.match(:a => 1).should == true
|
|
461
|
+
c.match(:a => nil).should == true
|
|
462
|
+
c.match({}).should == true
|
|
463
|
+
lambda { c.match(:a => 2)}.should not_match
|
|
464
|
+
end
|
|
465
|
+
end
|
|
466
|
+
end
|