case 0.5 → 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. data/README.rdoc +241 -0
  2. data/Rakefile +4 -3
  3. metadata +7 -4
@@ -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: "0.5"
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: 2008-08-13 00:00:00 -04:00
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.1.1
55
+ rubygems_version: 1.3.5
53
56
  signing_key:
54
- specification_version: 2
57
+ specification_version: 3
55
58
  summary: Pattern matching for Ruby
56
59
  test_files:
57
60
  - test/test_all.rb