case 0.5 → 0.5.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/README.rdoc +241 -0
- data/Rakefile +4 -3
- metadata +7 -4
data/README.rdoc
ADDED
@@ -0,0 +1,241 @@
|
|
1
|
+
= case
|
2
|
+
|
3
|
+
The case gem is a power-up for Ruby's case-matching.
|
4
|
+
|
5
|
+
== Structs
|
6
|
+
|
7
|
+
<code>Case::Struct</code> is a subclass of Ruby's standard <code>Struct</code>
|
8
|
+
class that supports structural matching. When two instances of a normal Ruby
|
9
|
+
<code>Struct</code> are matched, their fields are compared using the normal
|
10
|
+
equality test. <code>Case::Struct</code> uses the case-matching
|
11
|
+
<code>===</code> operator instead.
|
12
|
+
|
13
|
+
Here's an example of some of the things which are possible:
|
14
|
+
|
15
|
+
require 'case'
|
16
|
+
|
17
|
+
Foo = Case::Struct.new :foo
|
18
|
+
|
19
|
+
[Foo["blah"], Foo["hoge"], Foo[3], Foo["testing"]].each do |value|
|
20
|
+
case value
|
21
|
+
when Foo["testing"]
|
22
|
+
puts "matched testing"
|
23
|
+
when Foo["blah"]
|
24
|
+
puts "matched blah"
|
25
|
+
when Foo[String]
|
26
|
+
puts "matched string #{value.foo}"
|
27
|
+
else
|
28
|
+
puts "fell through"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
This will print:
|
33
|
+
|
34
|
+
matched blah
|
35
|
+
matched string hoge
|
36
|
+
fell through
|
37
|
+
matched testing
|
38
|
+
|
39
|
+
== Wildcards
|
40
|
+
|
41
|
+
The case gem also supports wildcards. For example:
|
42
|
+
|
43
|
+
require 'case'
|
44
|
+
|
45
|
+
Foo = Case::Struct :name, :arg
|
46
|
+
|
47
|
+
[Foo["blah", 9], Foo["meat", 5], Foo["blah", 23]].each do |value|
|
48
|
+
case value
|
49
|
+
when Foo["blah", Case::Any]
|
50
|
+
puts "blah: #{value.arg}"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
This will print:
|
55
|
+
|
56
|
+
blah: 9
|
57
|
+
blah: 23
|
58
|
+
|
59
|
+
<code>Case::Any</code> can also be used directly, though there's seldom
|
60
|
+
reason to do so instead of using an <code>else</code> clause.
|
61
|
+
|
62
|
+
case thing
|
63
|
+
when "foo"
|
64
|
+
# specific case
|
65
|
+
when Case::Any
|
66
|
+
# fall-through
|
67
|
+
end
|
68
|
+
|
69
|
+
case thing
|
70
|
+
when "foo"
|
71
|
+
# specific case
|
72
|
+
else
|
73
|
+
# fall-through
|
74
|
+
end
|
75
|
+
|
76
|
+
== Conjunction
|
77
|
+
|
78
|
+
Case also supports simultaneously testing several cases in a single when:
|
79
|
+
|
80
|
+
[4.5, 3, 3.0].each do |value|
|
81
|
+
case value
|
82
|
+
when Case::All[Float, 3]
|
83
|
+
puts "float 3"
|
84
|
+
when 3
|
85
|
+
puts "generic 3"
|
86
|
+
when Float
|
87
|
+
puts "generic float"
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
This prints:
|
92
|
+
|
93
|
+
generic float
|
94
|
+
generic 3
|
95
|
+
float 3
|
96
|
+
|
97
|
+
== Disjunction
|
98
|
+
|
99
|
+
It's also possible to match one of several alternatives, if you pass
|
100
|
+
arguments to <code>Case::Any</code>:
|
101
|
+
|
102
|
+
require 'rational'
|
103
|
+
require 'case'
|
104
|
+
|
105
|
+
[3, Rational(3, 1), 6.0, 3.0].each do |value|
|
106
|
+
case value
|
107
|
+
when Case::All[Case::Any[Float, Rational], 3]
|
108
|
+
puts "matched #{value.inspect}"
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
Which prints:
|
113
|
+
|
114
|
+
matched Rational(3, 1)
|
115
|
+
matched 3.0
|
116
|
+
|
117
|
+
Once again, <code>Case::Any</code> can be used on its own, though usually
|
118
|
+
there's not much point.
|
119
|
+
|
120
|
+
case thing
|
121
|
+
when Case::Any["foo", "bar"]
|
122
|
+
# either of these
|
123
|
+
end
|
124
|
+
|
125
|
+
case thing
|
126
|
+
when "foo", "bar"
|
127
|
+
# either of these
|
128
|
+
end
|
129
|
+
|
130
|
+
(Note that <code>Case::Any[]</code> with no arguments matches nothing; it
|
131
|
+
is different from <code>Case::Any</code> without braces.)
|
132
|
+
|
133
|
+
== Comparisons
|
134
|
+
|
135
|
+
<code>Case::Cmp</code> can be used to perform comparisons as part of
|
136
|
+
case-matching:
|
137
|
+
|
138
|
+
require 'case'
|
139
|
+
|
140
|
+
[0..5].each do |value|
|
141
|
+
case value
|
142
|
+
when 0, 1
|
143
|
+
puts "0 or 1"
|
144
|
+
when Case::Cmp < 4
|
145
|
+
puts "less than 4"
|
146
|
+
else
|
147
|
+
puts "fell through"
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
This prints:
|
152
|
+
|
153
|
+
0 or 1
|
154
|
+
0 or 1
|
155
|
+
less than 4
|
156
|
+
less than 4
|
157
|
+
fell through
|
158
|
+
fell through
|
159
|
+
|
160
|
+
The <, >, >= and <= operators are all supported.
|
161
|
+
|
162
|
+
== Guards
|
163
|
+
|
164
|
+
More general tests can be put in when statements using <code>Case::Guard</code>.
|
165
|
+
|
166
|
+
require 'case'
|
167
|
+
|
168
|
+
["foobar", "beef", "lorem"].each do |value|
|
169
|
+
case value
|
170
|
+
when Case::Guard.new { |v| v[1, 1] == "o" }
|
171
|
+
puts "second letter in #{value} is o"
|
172
|
+
else
|
173
|
+
puts "just got #{value}"
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
This will print:
|
178
|
+
|
179
|
+
second letter in foobar is o
|
180
|
+
just got beef
|
181
|
+
second letter in lorem is o
|
182
|
+
|
183
|
+
(Yes, I realize a regular expression could be used for this purpose.)
|
184
|
+
|
185
|
+
In simple cases, when <code>Case::Guard</code> is being used directly, you
|
186
|
+
don't even need to bother with the block parameter:
|
187
|
+
|
188
|
+
["foobar", "beef", "lorem"].each do |value|
|
189
|
+
case value
|
190
|
+
when Case::Guard.new { value[1, 1] == "o" }
|
191
|
+
puts "second letter in #{value} is o"
|
192
|
+
else
|
193
|
+
puts "just got #{value}"
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
(The parameter is really only there for when <code>Case::Guard</code> is
|
198
|
+
being used as part of a larger expression.)
|
199
|
+
|
200
|
+
== Negation
|
201
|
+
|
202
|
+
<code>Case::Not</code> inverts the normal matching. For example:
|
203
|
+
|
204
|
+
[1, "foobar", :blah].each do |value|
|
205
|
+
case value
|
206
|
+
when Case::Not[String]
|
207
|
+
puts value.inspect
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
This will print:
|
212
|
+
|
213
|
+
1
|
214
|
+
:blah
|
215
|
+
|
216
|
+
== Arrays
|
217
|
+
|
218
|
+
<code>Case::Array</code> is a subclass of <code>Array</code> which can
|
219
|
+
be used as a pattern to do positional matching in arrays:
|
220
|
+
|
221
|
+
require 'case'
|
222
|
+
|
223
|
+
[["foo", 2], ["bar", 3, 4], ["bar", 9]].each do |value|
|
224
|
+
case value
|
225
|
+
when Case::Array["foo", Case::Any]
|
226
|
+
puts "Foo #{value[1]}"
|
227
|
+
when Case::Array["bar", Case::Any]
|
228
|
+
puts "Bar #{value[1]}"
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
This will print:
|
233
|
+
|
234
|
+
Foo 2
|
235
|
+
Bar 9
|
236
|
+
|
237
|
+
Note that <code>Case::Array</code> only matches arrays of the same
|
238
|
+
length.
|
239
|
+
|
240
|
+
<code>Case::Array</code> should only be used as a pattern; there's no
|
241
|
+
need to use it in lieu of <code>Array</code> for your actual data.
|
data/Rakefile
CHANGED
@@ -4,10 +4,11 @@ require 'rake/rdoctask'
|
|
4
4
|
require 'rake/gempackagetask'
|
5
5
|
require 'rake/clean'
|
6
6
|
|
7
|
-
GEM_VERSION = "0.5"
|
7
|
+
GEM_VERSION = "0.5.1"
|
8
8
|
|
9
9
|
Rake::RDocTask.new do |task|
|
10
|
-
task.rdoc_files.add [ 'lib/**/*.rb' ]
|
10
|
+
task.rdoc_files.add [ 'lib/**/*.rb', 'README.rdoc' ]
|
11
|
+
task.main = 'README.rdoc'
|
11
12
|
end
|
12
13
|
|
13
14
|
task :clobber => [ :clean ]
|
@@ -27,7 +28,7 @@ gemspec = Gem::Specification.new do |gemspec|
|
|
27
28
|
gemspec.author = "MenTaLguY <mental@rydia.net>"
|
28
29
|
gemspec.summary = "Pattern matching for Ruby"
|
29
30
|
gemspec.test_file = 'test/test_all.rb'
|
30
|
-
gemspec.files = FileList[ 'Rakefile', 'test/*.rb', 'lib/**/*.rb' ]
|
31
|
+
gemspec.files = FileList[ 'Rakefile', 'README.rdoc', 'test/*.rb', 'lib/**/*.rb' ]
|
31
32
|
gemspec.require_paths = [ 'lib' ]
|
32
33
|
gemspec.has_rdoc = true
|
33
34
|
gemspec.platform = Gem::Platform::RUBY
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: case
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 0.5.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- MenTaLguY <mental@rydia.net>
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date:
|
12
|
+
date: 2010-12-09 00:00:00 -08:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -23,12 +23,15 @@ extra_rdoc_files: []
|
|
23
23
|
|
24
24
|
files:
|
25
25
|
- Rakefile
|
26
|
+
- README.rdoc
|
26
27
|
- test/test_case.rb
|
27
28
|
- test/test_all.rb
|
28
29
|
- lib/case.rb
|
29
30
|
- lib/case/core.rb
|
30
31
|
has_rdoc: true
|
31
32
|
homepage:
|
33
|
+
licenses: []
|
34
|
+
|
32
35
|
post_install_message:
|
33
36
|
rdoc_options: []
|
34
37
|
|
@@ -49,9 +52,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
49
52
|
requirements: []
|
50
53
|
|
51
54
|
rubyforge_project: concurrent
|
52
|
-
rubygems_version: 1.
|
55
|
+
rubygems_version: 1.3.5
|
53
56
|
signing_key:
|
54
|
-
specification_version:
|
57
|
+
specification_version: 3
|
55
58
|
summary: Pattern matching for Ruby
|
56
59
|
test_files:
|
57
60
|
- test/test_all.rb
|