functional-ruby 0.7.2 → 0.7.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,3 @@
1
- module Functional
2
- VERSION = '0.7.2'
3
- end
1
+ module Functional
2
+ VERSION = '0.7.3'
3
+ end
@@ -1 +1 @@
1
- require 'functional'
1
+ require 'functional'
data/md/behavior.md CHANGED
@@ -1,188 +1,188 @@
1
- # For good -behavior(timeoff).
2
-
3
- One of Ruby's greatest strengths is [duck typing](http://rubylearning.com/satishtalim/duck_typing.html).
4
- Usually this is awesome and I'm happy to not have to deal with static typing and the compiler. Usually.
5
- The problem with duck typing is that is is impossible in Ruby to enforce an interface definition.
6
- I would never advocate turning Ruby into the cesspool complex object creation that Java has
7
- unfortunately become, but occasionally it would be nice to make sure a class implements a set of
8
- required methods. Enter Erlang's [-behavior](http://metajack.im/2008/10/29/custom-behaviors-in-erlang/)
9
- keyword. Basically, you define a `behavior_info` then drop a `behavior` call within a class.
10
- Forget to implement a required method and Ruby will let you know. See the examples below for details.
11
-
12
- ## Usage
13
-
14
- Require the gem
15
-
16
- ```ruby
17
- require 'functional'
18
- ```
19
-
20
- ### behavior_info
21
-
22
- Next, declare a behavior using the `behavior_info` function (this function should sit outside
23
- of any module/class definition, but will probably work regardless). The first parameter to
24
- `behavior_info` (or `behaviour_info`) is a symbol name for the behavior. The remaining parameter
25
- is a hash of function names and their arity:
26
-
27
- ```ruby
28
- behaviour_info(:gen_foo, foo: 0, bar: 1, baz: 2)
29
-
30
- # -or (for the Java/C# crowd)
31
-
32
- interface(:gen_foo, foo: 0, bar: 1, baz: 2)
33
- ```
34
-
35
- Each function name can be listed only once and the arity must follow the rules of the
36
- [Method#arity](http://ruby-doc.org/core-1.9.3/Method.html#method-i-arity) function.
37
- Though not explicitly documented, block arguments do not count toward a method's arity.
38
- methods defined using this gem's `defn` function will always have an arity of -1,
39
- regardless of how many overloads are defined.
40
-
41
- To specify class/module methods prepend the methid name with 'self_'
42
-
43
- ```ruby
44
- behaviour_info(:gen_foo, self_foo: 0, self_bar: 1, baz: 2)
45
- ```
46
-
47
- ### behavior
48
-
49
- To enforce a behavior on a class simply call the `behavior` function within the class,
50
- passing the name of the desired behavior:
51
-
52
- ```ruby
53
- class Foo
54
- behavior(:gen_foo)
55
- ...
56
- end
57
-
58
- # or use the idiomatic Erlang spelling
59
- class Bar
60
- behaviour(:gen_foo)
61
- ...
62
- end
63
-
64
- # or use the idiomatic Rails syntax
65
- class Baz
66
- behaves_as :gen_foo
67
- ...
68
- end
69
- ```
70
-
71
- Make sure you the implement the required methods in your class. If you don't, Ruby will
72
- raise an exception when you try to create an object from the class:
73
-
74
- ```ruby
75
- Baz.new #=> ArgumentError: undefined callback functions in Baz (behavior 'gen_foo')
76
- ```
77
-
78
- A class may support multiple behaviors:
79
-
80
- ```ruby
81
- behavior_info(:gen_foo, foo: 0)
82
- behavior_info(:gen_bar, bar: 1)
83
-
84
- class FooBar
85
- behavior(:gen_foo)
86
- behavior(:gen_bar)
87
- ...
88
- end
89
- ```
90
-
91
- Inheritance and module inclusion are supported as well:
92
-
93
- ```ruby
94
- behavior_info(:gen_foo, foo: 0)
95
- behavior_info(:gen_bar, bar: 0)
96
-
97
- class Foo
98
- behavior(:gen_foo)
99
- def foo() nil; end
100
- end
101
-
102
- module Bar
103
- behavior(:gen_bar)
104
- def bar() nil; end
105
- end
106
-
107
- class FooBar < Foo
108
- include Bar
109
- end
110
-
111
- foobar = FooBar.new
112
-
113
- foobar.behaves_as?(:gen_foo) #=> true
114
- foobar.behaves_as?(:gen_bar) #=> true
115
- ```
116
-
117
- ### behaves_as?
118
-
119
- As an added bonus, Ruby [Object](http://ruby-doc.org/core-1.9.3/Object.html) will be
120
- monkey-patched with a `behaves_as?` predicate method.
121
-
122
- ## Example
123
-
124
- A complete example:
125
-
126
- ```ruby
127
- behaviour_info(:gen_foo, self_foo: 0, bar: 1, baz: 2, boom: -1, bam: :any)
128
-
129
- class Foo
130
- behavior(:gen_foo)
131
-
132
- def self.foo
133
- return 'foo/0'
134
- end
135
-
136
- def bar(one, &block)
137
- return 'bar/1'
138
- end
139
-
140
- def baz(one, two)
141
- return 'baz/2'
142
- end
143
-
144
- def boom(*args)
145
- return 'boom/-1'
146
- end
147
-
148
- def bam
149
- return 'bam!'
150
- end
151
- end
152
-
153
- foo = Foo.new
154
-
155
- Foo.behaves_as? :gen_foo #=> true
156
- foo.behaves_as? :gen_foo #=> true
157
- foo.behaves_as?(:bogus) #=> false
158
- 'foo'.behaves_as? :gen_foo #=> false
159
- ```
160
-
161
- ## Copyright
162
-
163
- *Functional Ruby* is Copyright &copy; 2013 [Jerry D'Antonio](https://twitter.com/jerrydantonio).
164
- It is free software and may be redistributed under the terms specified in the LICENSE file.
165
-
166
- ## License
167
-
168
- Released under the MIT license.
169
-
170
- http://www.opensource.org/licenses/mit-license.php
171
-
172
- > Permission is hereby granted, free of charge, to any person obtaining a copy
173
- > of this software and associated documentation files (the "Software"), to deal
174
- > in the Software without restriction, including without limitation the rights
175
- > to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
176
- > copies of the Software, and to permit persons to whom the Software is
177
- > furnished to do so, subject to the following conditions:
178
- >
179
- > The above copyright notice and this permission notice shall be included in
180
- > all copies or substantial portions of the Software.
181
- >
182
- > THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
183
- > IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
184
- > FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
185
- > AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
186
- > LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
187
- > OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
188
- > THE SOFTWARE.
1
+ # For good -behavior(:timeoff).
2
+
3
+ One of Ruby's greatest strengths is [duck typing](http://rubylearning.com/satishtalim/duck_typing.html).
4
+ Usually this is awesome and I'm happy to not have to deal with static typing and the compiler. Usually.
5
+ The problem with duck typing is that is is impossible in Ruby to enforce an interface definition.
6
+ I would never advocate turning Ruby into the cesspool complex object creation that Java has
7
+ unfortunately become, but occasionally it would be nice to make sure a class implements a set of
8
+ required methods. Enter Erlang's [-behavior](http://metajack.im/2008/10/29/custom-behaviors-in-erlang/)
9
+ keyword. Basically, you define a `behavior_info` then drop a `behavior` call within a class.
10
+ Forget to implement a required method and Ruby will let you know. See the examples below for details.
11
+
12
+ ## Usage
13
+
14
+ Require the gem
15
+
16
+ ```ruby
17
+ require 'functional'
18
+ ```
19
+
20
+ ### behavior_info
21
+
22
+ Next, declare a behavior using the `behavior_info` function (this function should sit outside
23
+ of any module/class definition, but will probably work regardless). The first parameter to
24
+ `behavior_info` (or `behaviour_info`) is a symbol name for the behavior. The remaining parameter
25
+ is a hash of function names and their arity:
26
+
27
+ ```ruby
28
+ behaviour_info(:gen_foo, foo: 0, bar: 1, baz: 2)
29
+
30
+ # -or (for the Java/C# crowd)
31
+
32
+ interface(:gen_foo, foo: 0, bar: 1, baz: 2)
33
+ ```
34
+
35
+ Each function name can be listed only once and the arity must follow the rules of the
36
+ [Method#arity](http://ruby-doc.org/core-1.9.3/Method.html#method-i-arity) function.
37
+ Though not explicitly documented, block arguments do not count toward a method's arity.
38
+ methods defined using this gem's `defn` function will always have an arity of -1,
39
+ regardless of how many overloads are defined.
40
+
41
+ To specify class/module methods prepend the methid name with 'self_'
42
+
43
+ ```ruby
44
+ behaviour_info(:gen_foo, self_foo: 0, self_bar: 1, baz: 2)
45
+ ```
46
+
47
+ ### behavior
48
+
49
+ To enforce a behavior on a class simply call the `behavior` function within the class,
50
+ passing the name of the desired behavior:
51
+
52
+ ```ruby
53
+ class Foo
54
+ behavior(:gen_foo)
55
+ ...
56
+ end
57
+
58
+ # or use the idiomatic Erlang spelling
59
+ class Bar
60
+ behaviour(:gen_foo)
61
+ ...
62
+ end
63
+
64
+ # or use the idiomatic Rails syntax
65
+ class Baz
66
+ behaves_as :gen_foo
67
+ ...
68
+ end
69
+ ```
70
+
71
+ Make sure you the implement the required methods in your class. If you don't, Ruby will
72
+ raise an exception when you try to create an object from the class:
73
+
74
+ ```ruby
75
+ Baz.new #=> ArgumentError: undefined callback functions in Baz (behavior 'gen_foo')
76
+ ```
77
+
78
+ A class may support multiple behaviors:
79
+
80
+ ```ruby
81
+ behavior_info(:gen_foo, foo: 0)
82
+ behavior_info(:gen_bar, bar: 1)
83
+
84
+ class FooBar
85
+ behavior(:gen_foo)
86
+ behavior(:gen_bar)
87
+ ...
88
+ end
89
+ ```
90
+
91
+ Inheritance and module inclusion are supported as well:
92
+
93
+ ```ruby
94
+ behavior_info(:gen_foo, foo: 0)
95
+ behavior_info(:gen_bar, bar: 0)
96
+
97
+ class Foo
98
+ behavior(:gen_foo)
99
+ def foo() nil; end
100
+ end
101
+
102
+ module Bar
103
+ behavior(:gen_bar)
104
+ def bar() nil; end
105
+ end
106
+
107
+ class FooBar < Foo
108
+ include Bar
109
+ end
110
+
111
+ foobar = FooBar.new
112
+
113
+ foobar.behaves_as?(:gen_foo) #=> true
114
+ foobar.behaves_as?(:gen_bar) #=> true
115
+ ```
116
+
117
+ ### behaves_as?
118
+
119
+ As an added bonus, Ruby [Object](http://ruby-doc.org/core-1.9.3/Object.html) will be
120
+ monkey-patched with a `behaves_as?` predicate method.
121
+
122
+ ## Example
123
+
124
+ A complete example:
125
+
126
+ ```ruby
127
+ behaviour_info(:gen_foo, self_foo: 0, bar: 1, baz: 2, boom: -1, bam: :any)
128
+
129
+ class Foo
130
+ behavior(:gen_foo)
131
+
132
+ def self.foo
133
+ return 'foo/0'
134
+ end
135
+
136
+ def bar(one, &block)
137
+ return 'bar/1'
138
+ end
139
+
140
+ def baz(one, two)
141
+ return 'baz/2'
142
+ end
143
+
144
+ def boom(*args)
145
+ return 'boom/-1'
146
+ end
147
+
148
+ def bam
149
+ return 'bam!'
150
+ end
151
+ end
152
+
153
+ foo = Foo.new
154
+
155
+ Foo.behaves_as? :gen_foo #=> true
156
+ foo.behaves_as? :gen_foo #=> true
157
+ foo.behaves_as?(:bogus) #=> false
158
+ 'foo'.behaves_as? :gen_foo #=> false
159
+ ```
160
+
161
+ ## Copyright
162
+
163
+ *Functional Ruby* is Copyright &copy; 2013 [Jerry D'Antonio](https://twitter.com/jerrydantonio).
164
+ It is free software and may be redistributed under the terms specified in the LICENSE file.
165
+
166
+ ## License
167
+
168
+ Released under the MIT license.
169
+
170
+ http://www.opensource.org/licenses/mit-license.php
171
+
172
+ > Permission is hereby granted, free of charge, to any person obtaining a copy
173
+ > of this software and associated documentation files (the "Software"), to deal
174
+ > in the Software without restriction, including without limitation the rights
175
+ > to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
176
+ > copies of the Software, and to permit persons to whom the Software is
177
+ > furnished to do so, subject to the following conditions:
178
+ >
179
+ > The above copyright notice and this permission notice shall be included in
180
+ > all copies or substantial portions of the Software.
181
+ >
182
+ > THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
183
+ > IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
184
+ > FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
185
+ > AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
186
+ > LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
187
+ > OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
188
+ > THE SOFTWARE.
@@ -1,512 +1,512 @@
1
- # Erlang-style Pattern Matching
2
-
3
- As much as I love Ruby I've always been a little disappointed that Ruby doesn't
4
- support function overloading. Function overloading tends to reduce branching
5
- and keep function signatures simpler. No sweat, I learned to do without. Then
6
- I started programming in Erlang. My favorite Erlang feature is, without
7
- question, pattern matching. Pattern matching is like function overloading
8
- cranked to 11. So one day I was musing on Twitter that I'd like to see
9
- Erlang-stype pattern matching in Ruby and one of my friends responded
10
- "Build it!" So I did. And here it is.
11
-
12
-
13
- ## Features
14
-
15
- * Pattern matching for instance methods.
16
- * Pattern matching for object constructors.
17
- * Parameter count matching
18
- * Matching against primitive values
19
- * Matching by class/datatype
20
- * Matching against specific key/vaue pairs in hashes
21
- * Matching against the presence of keys within hashes
22
- * Implicit hash for last parameter
23
- * Variable-length parameter lists
24
- * Guard clauses
25
- * Recursive calls to other pattern matches
26
- * Recursive calls to superclass pattern matches
27
- * Recursive calls to superclass methods
28
- * Dispatching to superclass methods when no match is found
29
- * Reasonable error messages when no match is found
30
-
31
- ## Usage
32
-
33
- First, familiarize yourself with Erlang [pattern matching](http://learnyousomeerlang.com/syntax-in-functions#pattern-matching).
34
- This gem may not make much sense if you don't understand how Erlang dispatches functions.
35
-
36
- In the Ruby class file where you want to use pattern matching, require the *functional-ruby* gem:
37
-
38
- ```ruby
39
- require 'functional/pattern_matching'
40
- ```
41
-
42
- Then include `PatternMatching` in your class:
43
-
44
- ```ruby
45
- require 'functional/pattern_matching'
46
-
47
- class Foo
48
- include PatternMatching
49
-
50
- ...
51
-
52
- end
53
- ```
54
-
55
- You can then define functions with `defn` instead of the normal *def* statement.
56
- The syntax for `defn` is:
57
-
58
- ```ruby
59
- defn(:symbol_name_of_function, zero, or, more, parameters) { |block, arguments|
60
- # code to execute
61
- }
62
- ```
63
- You can then call your new function just like any other:
64
-
65
- ```ruby
66
- require 'functional/pattern_matching'
67
-
68
- class Foo
69
- include PatternMatching
70
-
71
- defn(:hello) {
72
- puts "Hello, World!"
73
- }
74
- end
75
-
76
- foo = Foo.new
77
- foo.hello #=> "Hello, World!"
78
- ```
79
-
80
- Patterns to match against are included in the parameter list:
81
-
82
- ```ruby
83
- defn(:greet, :male) {
84
- puts "Hello, sir!"
85
- }
86
-
87
- defn(:greet, :female) {
88
- puts "Hello, ma'am!"
89
- }
90
-
91
- ...
92
-
93
- foo.greet(:male) #=> "Hello, sir!"
94
- foo.greet(:female) #=> "Hello, ma'am!"
95
- ```
96
-
97
- If a particular method call can not be matched a *NoMethodError* is thrown with
98
- a reasonably helpful error message:
99
-
100
- ```ruby
101
- foo.greet(:unknown) #=> NoMethodError: no method `greet` matching [:unknown] found for class Foo
102
- foo.greet #=> NoMethodError: no method `greet` matching [] found for class Foo
103
- ```
104
-
105
- Parameters that are expected to exist but that can take any value are considered
106
- *unbound* parameters. Unbound parameters are specified by the `_` underscore
107
- character or `UNBOUND`:
108
-
109
- ```ruby
110
- defn(:greet, _) do |name|
111
- "Hello, #{name}!"
112
- end
113
-
114
- defn(:greet, UNBOUND, UNBOUND) do |first, last|
115
- "Hello, #{first} #{last}!"
116
- end
117
-
118
- ...
119
-
120
- foo.greet('Jerry') #=> "Hello, Jerry!"
121
- ```
122
-
123
- All unbound parameters will be passed to the block in the order they are specified in the definition:
124
-
125
- ```ruby
126
- defn(:greet, _, _) do |first, last|
127
- "Hello, #{first} #{last}!"
128
- end
129
-
130
- ...
131
-
132
- foo.greet('Jerry', "D'Antonio") #=> "Hello, Jerry D'Antonio!"
133
- ```
134
-
135
- If for some reason you don't care about one or more unbound parameters within
136
- the block you can use the `_` underscore character in the block parameters list
137
- as well:
138
-
139
- ```ruby
140
- defn(:greet, _, _, _) do |first, _, last|
141
- "Hello, #{first} #{last}!"
142
- end
143
-
144
- ...
145
-
146
- foo.greet('Jerry', "I'm not going to tell you my middle name!", "D'Antonio") #=> "Hello, Jerry D'Antonio!"
147
- ```
148
-
149
- Hash parameters can match against specific keys and either bound or unbound parameters. This allows for
150
- function dispatch by hash parameters without having to dig through the hash:
151
-
152
- ```ruby
153
- defn(:hashable, {foo: :bar}) { |opts|
154
- :foo_bar
155
- }
156
- defn(:hashable, {foo: _}) { |f|
157
- f
158
- }
159
-
160
- ...
161
-
162
- foo.hashable({foo: :bar}) #=> :foo_bar
163
- foo.hashable({foo: :baz}) #=> :baz
164
- ```
165
-
166
- The Ruby idiom of the final parameter being a hash is also supported:
167
-
168
- ```ruby
169
- defn(:options, _) { |opts|
170
- opts
171
- }
172
-
173
- ...
174
-
175
- foo.options(bar: :baz, one: 1, many: 2)
176
- ```
177
-
178
- As is the Ruby idiom of variable-length argument lists. The constant `ALL` as the last parameter
179
- will match one or more arguments and pass them to the block as an array:
180
-
181
- ```ruby
182
- defn(:baz, Integer, ALL) { |int, args|
183
- [int, args]
184
- }
185
- defn(:baz, ALL) { |args|
186
- args
187
- }
188
- ```
189
-
190
- Superclass polymorphism is supported as well. If an object cannot match a method
191
- signature it will defer to the parent class:
192
-
193
- ```ruby
194
- class Bar
195
- def greet
196
- return 'Hello, World!'
197
- end
198
- end
199
-
200
- class Foo < Bar
201
- include PatternMatching
202
-
203
- defn(:greet, _) do |name|
204
- "Hello, #{name}!"
205
- end
206
- end
207
-
208
- ...
209
-
210
- foo.greet('Jerry') #=> "Hello, Jerry!"
211
- foo.greet #=> "Hello, World!"
212
- ```
213
-
214
- Guard clauses in Erlang are defined with `when` clauses between the parameter list and the function body.
215
- In Ruby, guard clauses are defined by chaining a call to `when` onto the the `defn` call and passing
216
- a block. If the guard clause evaluates to true then the function will match. If the guard evaluates
217
- to false the function will not match and pattern matching will continue:
218
-
219
- Erlang:
220
-
221
- ```erlang
222
- old_enough(X) when X >= 16 -> true;
223
- old_enough(_) -> false.
224
- ```
225
-
226
- Ruby:
227
-
228
- ```ruby
229
- defn(:old_enough, _){ true }.when{|x| x >= 16 }
230
- defn(:old_enough, _){ false }
231
- ```
232
-
233
- ### Order Matters
234
-
235
- As with Erlang, the order of pattern matches is significant. Patterns will be matched
236
- *in the order declared* and the first match will be used. If a particular function call
237
- can be matched by more than one pattern, the *first matched pattern* will be used. It
238
- is the programmer's responsibility to ensure patterns are declared in the correct order.
239
-
240
- ### Blocks and Procs and Lambdas, oh my!
241
-
242
- When using this gem it is critical to remember that `defn` takes a block and
243
- that blocks in Ruby have special rules. There are [plenty](https://www.google.com/search?q=ruby+block+proc+lambda)
244
- of good tutorials on the web explaining [blocks](http://www.robertsosinski.com/2008/12/21/understanding-ruby-blocks-procs-and-lambdas/)
245
- and [Procs](https://coderwall.com/p/_-_mha) and [lambdas](http://railsguru.org/2010/03/learn-ruby-procs-blocks-lambda/)
246
- in Ruby. Please read them. Please don't submit a bug report if you use a
247
- `return` statement within your `defn` and your code blows up with a
248
- [LocalJumpError](http://ruby-doc.org/core-2.0/LocalJumpError.html).
249
-
250
- ### Examples
251
-
252
- For more examples see the integration tests in *spec/integration_spec.rb*.
253
-
254
- #### Simple Functions
255
-
256
- This example is based on [Syntax in defnctions: Pattern Matching](http://learnyousomeerlang.com/syntax-in-defnctions) in [Learn You Some Erlang for Great Good!](http://learnyousomeerlang.com/).
257
-
258
- Erlang:
259
-
260
- ```erlang
261
- greet(male, Name) ->
262
- io:format("Hello, Mr. ~s!", [Name]);
263
- greet(female, Name) ->
264
- io:format("Hello, Mrs. ~s!", [Name]);
265
- greet(_, Name) ->
266
- io:format("Hello, ~s!", [Name]).
267
- ```
268
-
269
- Ruby:
270
-
271
- ```ruby
272
- require 'functional/pattern_matching'
273
-
274
- class Foo
275
- include PatternMatching
276
-
277
- defn(:greet, _) do |name|
278
- "Hello, #{name}!"
279
- end
280
-
281
- defn(:greet, :male, _) { |name|
282
- "Hello, Mr. #{name}!"
283
- }
284
- defn(:greet, :female, _) { |name|
285
- "Hello, Ms. #{name}!"
286
- }
287
- defn(:greet, _, _) { |_, name|
288
- "Hello, #{name}!"
289
- }
290
- end
291
- ```
292
-
293
- #### Simple Functions with Overloading
294
-
295
- This example is based on [Syntax in defnctions: Pattern Matching](http://learnyousomeerlang.com/syntax-in-defnctions) in [Learn You Some Erlang for Great Good!](http://learnyousomeerlang.com/).
296
-
297
- Erlang:
298
-
299
- ```erlang
300
- greet(Name) ->
301
- io:format("Hello, ~s!", [Name]).
302
-
303
- greet(male, Name) ->
304
- io:format("Hello, Mr. ~s!", [Name]);
305
- greet(female, Name) ->
306
- io:format("Hello, Mrs. ~s!", [Name]);
307
- greet(_, Name) ->
308
- io:format("Hello, ~s!", [Name]).
309
- ```
310
-
311
- Ruby:
312
-
313
- ```ruby
314
- require 'functional/pattern_matching'
315
-
316
- class Foo
317
- include PatternMatching
318
-
319
- defn(:greet, _) do |name|
320
- "Hello, #{name}!"
321
- end
322
-
323
- defn(:greet, :male, _) { |name|
324
- "Hello, Mr. #{name}!"
325
- }
326
- defn(:greet, :female, _) { |name|
327
- "Hello, Ms. #{name}!"
328
- }
329
- defn(:greet, nil, _) { |name|
330
- "Goodbye, #{name}!"
331
- }
332
- defn(:greet, _, _) { |_, name|
333
- "Hello, #{name}!"
334
- }
335
- end
336
- ```
337
-
338
- #### Constructor Overloading
339
-
340
- ```ruby
341
- require 'functional/pattern_matching'
342
-
343
- class Foo
344
- include PatternMatching
345
-
346
- defn(:initialize) { @name = 'baz' }
347
- defn(:initialize, _) {|name| @name = name.to_s }
348
- end
349
- ```
350
-
351
- #### Matching by Class/Datatype
352
-
353
- ```ruby
354
- require 'functional/pattern_matching'
355
-
356
- class Foo
357
- include PatternMatching
358
-
359
- defn(:concat, Integer, Integer) { |first, second|
360
- first + second
361
- }
362
- defn(:concat, Integer, String) { |first, second|
363
- "#{first} #{second}"
364
- }
365
- defn(:concat, String, String) { |first, second|
366
- first + second
367
- }
368
- defn(:concat, Integer, _) { |first, second|
369
- first + second.to_i
370
- }
371
- end
372
- ```
373
-
374
- #### Matching a Hash Parameter
375
-
376
- ```ruby
377
- require 'functional/pattern_matching'
378
-
379
- class Foo
380
- include PatternMatching
381
-
382
- defn(:hashable, {foo: :bar}) { |opts|
383
- # matches any hash with key :foo and value :bar
384
- :foo_bar
385
- }
386
- defn(:hashable, {foo: _, bar: _}) { |f, b|
387
- # matches any hash with keys :foo and :bar
388
- # passes the values associated with those keys to the block
389
- [f, b]
390
- }
391
- defn(:hashable, {foo: _}) { |f|
392
- # matches any hash with key :foo
393
- # passes the value associated with that key to the block
394
- # must appear AFTER the prior match or it will override that one
395
- f
396
- }
397
- defn(:hashable, {}) { ||
398
- # matches an empty hash
399
- :empty
400
- }
401
- defn(:hashable, _) { |opts|
402
- # matches any hash (or any other value)
403
- opts
404
- }
405
- end
406
-
407
- ...
408
-
409
- foo.hashable({foo: :bar}) #=> :foo_bar
410
- foo.hashable({foo: :baz}) #=> :baz
411
- foo.hashable({foo: 1, bar: 2}) #=> [1, 2]
412
- foo.hashable({foo: 1, baz: 2}) #=> 1
413
- foo.hashable({bar: :baz}) #=> {bar: :baz}
414
- foo.hashable({}) #=> :empty
415
- ```
416
-
417
- #### Variable Length Argument Lists with ALL
418
-
419
- ```ruby
420
- defn(:all, :one, ALL) { |args|
421
- args
422
- }
423
- defn(:all, :one, Integer, ALL) { |int, args|
424
- [int, args]
425
- }
426
- defn(:all, 1, _, ALL) { |var, args|
427
- [var, args]
428
- }
429
- defn(:all, ALL) { | args|
430
- args
431
- }
432
-
433
- ...
434
-
435
- foo.all(:one, 'a', 'bee', :see) #=> ['a', 'bee', :see]
436
- foo.all(:one, 1, 'bee', :see) #=> [1, 'bee', :see]
437
- foo.all(1, 'a', 'bee', :see) #=> ['a', ['bee', :see]]
438
- foo.all('a', 'bee', :see) #=> ['a', 'bee', :see]
439
- foo.all() #=> NoMethodError: no method `all` matching [] found for class Foo
440
- ```
441
-
442
- #### Guard Clauses
443
-
444
- These examples are based on [Syntax in defnctions: Pattern Matching](http://learnyousomeerlang.com/syntax-in-defnctions)
445
- in [Learn You Some Erlang for Great Good!](http://learnyousomeerlang.com/).
446
-
447
- Erlang:
448
-
449
- ```erlang
450
- old_enough(X) when X >= 16 -> true;
451
- old_enough(_) -> false.
452
-
453
- right_age(X) when X >= 16, X =< 104 ->
454
- true;
455
- right_age(_) ->
456
- false.
457
-
458
- wrong_age(X) when X < 16; X > 104 ->
459
- true;
460
- wrong_age(_) ->
461
- false.
462
- ```
463
-
464
- ```ruby
465
- defn(:old_enough, _){ true }.when{|x| x >= 16 }
466
- defn(:old_enough, _){ false }
467
-
468
- defn(:right_age, _) {
469
- true
470
- }.when{|x| x >= 16 && x <= 104 }
471
-
472
- defn(:right_age, _) {
473
- false
474
- }
475
-
476
- defn(:wrong_age, _) {
477
- false
478
- }.when{|x| x < 16 || x > 104 }
479
-
480
- defn(:wrong_age, _) {
481
- true
482
- }
483
- ```
484
-
485
- ## Copyright
486
-
487
- *Functional Ruby* is Copyright &copy; 2013 [Jerry D'Antonio](https://twitter.com/jerrydantonio).
488
- It is free software and may be redistributed under the terms specified in the LICENSE file.
489
-
490
- ## License
491
-
492
- Released under the MIT license.
493
-
494
- http://www.opensource.org/licenses/mit-license.php
495
-
496
- > Permission is hereby granted, free of charge, to any person obtaining a copy
497
- > of this software and associated documentation files (the "Software"), to deal
498
- > in the Software without restriction, including without limitation the rights
499
- > to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
500
- > copies of the Software, and to permit persons to whom the Software is
501
- > furnished to do so, subject to the following conditions:
502
- >
503
- > The above copyright notice and this permission notice shall be included in
504
- > all copies or substantial portions of the Software.
505
- >
506
- > THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
507
- > IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
508
- > FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
509
- > AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
510
- > LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
511
- > OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
512
- > THE SOFTWARE.
1
+ # Erlang-style Pattern Matching
2
+
3
+ As much as I love Ruby I've always been a little disappointed that Ruby doesn't
4
+ support function overloading. Function overloading tends to reduce branching
5
+ and keep function signatures simpler. No sweat, I learned to do without. Then
6
+ I started programming in Erlang. My favorite Erlang feature is, without
7
+ question, pattern matching. Pattern matching is like function overloading
8
+ cranked to 11. So one day I was musing on Twitter that I'd like to see
9
+ Erlang-stype pattern matching in Ruby and one of my friends responded
10
+ "Build it!" So I did. And here it is.
11
+
12
+
13
+ ## Features
14
+
15
+ * Pattern matching for instance methods.
16
+ * Pattern matching for object constructors.
17
+ * Parameter count matching
18
+ * Matching against primitive values
19
+ * Matching by class/datatype
20
+ * Matching against specific key/vaue pairs in hashes
21
+ * Matching against the presence of keys within hashes
22
+ * Implicit hash for last parameter
23
+ * Variable-length parameter lists
24
+ * Guard clauses
25
+ * Recursive calls to other pattern matches
26
+ * Recursive calls to superclass pattern matches
27
+ * Recursive calls to superclass methods
28
+ * Dispatching to superclass methods when no match is found
29
+ * Reasonable error messages when no match is found
30
+
31
+ ## Usage
32
+
33
+ First, familiarize yourself with Erlang [pattern matching](http://learnyousomeerlang.com/syntax-in-functions#pattern-matching).
34
+ This gem may not make much sense if you don't understand how Erlang dispatches functions.
35
+
36
+ In the Ruby class file where you want to use pattern matching, require the *functional-ruby* gem:
37
+
38
+ ```ruby
39
+ require 'functional/pattern_matching'
40
+ ```
41
+
42
+ Then include `PatternMatching` in your class:
43
+
44
+ ```ruby
45
+ require 'functional/pattern_matching'
46
+
47
+ class Foo
48
+ include PatternMatching
49
+
50
+ ...
51
+
52
+ end
53
+ ```
54
+
55
+ You can then define functions with `defn` instead of the normal *def* statement.
56
+ The syntax for `defn` is:
57
+
58
+ ```ruby
59
+ defn(:symbol_name_of_function, zero, or, more, parameters) { |block, arguments|
60
+ # code to execute
61
+ }
62
+ ```
63
+ You can then call your new function just like any other:
64
+
65
+ ```ruby
66
+ require 'functional/pattern_matching'
67
+
68
+ class Foo
69
+ include PatternMatching
70
+
71
+ defn(:hello) {
72
+ puts "Hello, World!"
73
+ }
74
+ end
75
+
76
+ foo = Foo.new
77
+ foo.hello #=> "Hello, World!"
78
+ ```
79
+
80
+ Patterns to match against are included in the parameter list:
81
+
82
+ ```ruby
83
+ defn(:greet, :male) {
84
+ puts "Hello, sir!"
85
+ }
86
+
87
+ defn(:greet, :female) {
88
+ puts "Hello, ma'am!"
89
+ }
90
+
91
+ ...
92
+
93
+ foo.greet(:male) #=> "Hello, sir!"
94
+ foo.greet(:female) #=> "Hello, ma'am!"
95
+ ```
96
+
97
+ If a particular method call can not be matched a *NoMethodError* is thrown with
98
+ a reasonably helpful error message:
99
+
100
+ ```ruby
101
+ foo.greet(:unknown) #=> NoMethodError: no method `greet` matching [:unknown] found for class Foo
102
+ foo.greet #=> NoMethodError: no method `greet` matching [] found for class Foo
103
+ ```
104
+
105
+ Parameters that are expected to exist but that can take any value are considered
106
+ *unbound* parameters. Unbound parameters are specified by the `_` underscore
107
+ character or `UNBOUND`:
108
+
109
+ ```ruby
110
+ defn(:greet, _) do |name|
111
+ "Hello, #{name}!"
112
+ end
113
+
114
+ defn(:greet, UNBOUND, UNBOUND) do |first, last|
115
+ "Hello, #{first} #{last}!"
116
+ end
117
+
118
+ ...
119
+
120
+ foo.greet('Jerry') #=> "Hello, Jerry!"
121
+ ```
122
+
123
+ All unbound parameters will be passed to the block in the order they are specified in the definition:
124
+
125
+ ```ruby
126
+ defn(:greet, _, _) do |first, last|
127
+ "Hello, #{first} #{last}!"
128
+ end
129
+
130
+ ...
131
+
132
+ foo.greet('Jerry', "D'Antonio") #=> "Hello, Jerry D'Antonio!"
133
+ ```
134
+
135
+ If for some reason you don't care about one or more unbound parameters within
136
+ the block you can use the `_` underscore character in the block parameters list
137
+ as well:
138
+
139
+ ```ruby
140
+ defn(:greet, _, _, _) do |first, _, last|
141
+ "Hello, #{first} #{last}!"
142
+ end
143
+
144
+ ...
145
+
146
+ foo.greet('Jerry', "I'm not going to tell you my middle name!", "D'Antonio") #=> "Hello, Jerry D'Antonio!"
147
+ ```
148
+
149
+ Hash parameters can match against specific keys and either bound or unbound parameters. This allows for
150
+ function dispatch by hash parameters without having to dig through the hash:
151
+
152
+ ```ruby
153
+ defn(:hashable, {foo: :bar}) { |opts|
154
+ :foo_bar
155
+ }
156
+ defn(:hashable, {foo: _}) { |f|
157
+ f
158
+ }
159
+
160
+ ...
161
+
162
+ foo.hashable({foo: :bar}) #=> :foo_bar
163
+ foo.hashable({foo: :baz}) #=> :baz
164
+ ```
165
+
166
+ The Ruby idiom of the final parameter being a hash is also supported:
167
+
168
+ ```ruby
169
+ defn(:options, _) { |opts|
170
+ opts
171
+ }
172
+
173
+ ...
174
+
175
+ foo.options(bar: :baz, one: 1, many: 2)
176
+ ```
177
+
178
+ As is the Ruby idiom of variable-length argument lists. The constant `ALL` as the last parameter
179
+ will match one or more arguments and pass them to the block as an array:
180
+
181
+ ```ruby
182
+ defn(:baz, Integer, ALL) { |int, args|
183
+ [int, args]
184
+ }
185
+ defn(:baz, ALL) { |args|
186
+ args
187
+ }
188
+ ```
189
+
190
+ Superclass polymorphism is supported as well. If an object cannot match a method
191
+ signature it will defer to the parent class:
192
+
193
+ ```ruby
194
+ class Bar
195
+ def greet
196
+ return 'Hello, World!'
197
+ end
198
+ end
199
+
200
+ class Foo < Bar
201
+ include PatternMatching
202
+
203
+ defn(:greet, _) do |name|
204
+ "Hello, #{name}!"
205
+ end
206
+ end
207
+
208
+ ...
209
+
210
+ foo.greet('Jerry') #=> "Hello, Jerry!"
211
+ foo.greet #=> "Hello, World!"
212
+ ```
213
+
214
+ Guard clauses in Erlang are defined with `when` clauses between the parameter list and the function body.
215
+ In Ruby, guard clauses are defined by chaining a call to `when` onto the the `defn` call and passing
216
+ a block. If the guard clause evaluates to true then the function will match. If the guard evaluates
217
+ to false the function will not match and pattern matching will continue:
218
+
219
+ Erlang:
220
+
221
+ ```erlang
222
+ old_enough(X) when X >= 16 -> true;
223
+ old_enough(_) -> false.
224
+ ```
225
+
226
+ Ruby:
227
+
228
+ ```ruby
229
+ defn(:old_enough, _){ true }.when{|x| x >= 16 }
230
+ defn(:old_enough, _){ false }
231
+ ```
232
+
233
+ ### Order Matters
234
+
235
+ As with Erlang, the order of pattern matches is significant. Patterns will be matched
236
+ *in the order declared* and the first match will be used. If a particular function call
237
+ can be matched by more than one pattern, the *first matched pattern* will be used. It
238
+ is the programmer's responsibility to ensure patterns are declared in the correct order.
239
+
240
+ ### Blocks and Procs and Lambdas, oh my!
241
+
242
+ When using this gem it is critical to remember that `defn` takes a block and
243
+ that blocks in Ruby have special rules. There are [plenty](https://www.google.com/search?q=ruby+block+proc+lambda)
244
+ of good tutorials on the web explaining [blocks](http://www.robertsosinski.com/2008/12/21/understanding-ruby-blocks-procs-and-lambdas/)
245
+ and [Procs](https://coderwall.com/p/_-_mha) and [lambdas](http://railsguru.org/2010/03/learn-ruby-procs-blocks-lambda/)
246
+ in Ruby. Please read them. Please don't submit a bug report if you use a
247
+ `return` statement within your `defn` and your code blows up with a
248
+ [LocalJumpError](http://ruby-doc.org/core-2.0/LocalJumpError.html).
249
+
250
+ ### Examples
251
+
252
+ For more examples see the integration tests in *spec/integration_spec.rb*.
253
+
254
+ #### Simple Functions
255
+
256
+ This example is based on [Syntax in defnctions: Pattern Matching](http://learnyousomeerlang.com/syntax-in-defnctions) in [Learn You Some Erlang for Great Good!](http://learnyousomeerlang.com/).
257
+
258
+ Erlang:
259
+
260
+ ```erlang
261
+ greet(male, Name) ->
262
+ io:format("Hello, Mr. ~s!", [Name]);
263
+ greet(female, Name) ->
264
+ io:format("Hello, Mrs. ~s!", [Name]);
265
+ greet(_, Name) ->
266
+ io:format("Hello, ~s!", [Name]).
267
+ ```
268
+
269
+ Ruby:
270
+
271
+ ```ruby
272
+ require 'functional/pattern_matching'
273
+
274
+ class Foo
275
+ include PatternMatching
276
+
277
+ defn(:greet, _) do |name|
278
+ "Hello, #{name}!"
279
+ end
280
+
281
+ defn(:greet, :male, _) { |name|
282
+ "Hello, Mr. #{name}!"
283
+ }
284
+ defn(:greet, :female, _) { |name|
285
+ "Hello, Ms. #{name}!"
286
+ }
287
+ defn(:greet, _, _) { |_, name|
288
+ "Hello, #{name}!"
289
+ }
290
+ end
291
+ ```
292
+
293
+ #### Simple Functions with Overloading
294
+
295
+ This example is based on [Syntax in defnctions: Pattern Matching](http://learnyousomeerlang.com/syntax-in-defnctions) in [Learn You Some Erlang for Great Good!](http://learnyousomeerlang.com/).
296
+
297
+ Erlang:
298
+
299
+ ```erlang
300
+ greet(Name) ->
301
+ io:format("Hello, ~s!", [Name]).
302
+
303
+ greet(male, Name) ->
304
+ io:format("Hello, Mr. ~s!", [Name]);
305
+ greet(female, Name) ->
306
+ io:format("Hello, Mrs. ~s!", [Name]);
307
+ greet(_, Name) ->
308
+ io:format("Hello, ~s!", [Name]).
309
+ ```
310
+
311
+ Ruby:
312
+
313
+ ```ruby
314
+ require 'functional/pattern_matching'
315
+
316
+ class Foo
317
+ include PatternMatching
318
+
319
+ defn(:greet, _) do |name|
320
+ "Hello, #{name}!"
321
+ end
322
+
323
+ defn(:greet, :male, _) { |name|
324
+ "Hello, Mr. #{name}!"
325
+ }
326
+ defn(:greet, :female, _) { |name|
327
+ "Hello, Ms. #{name}!"
328
+ }
329
+ defn(:greet, nil, _) { |name|
330
+ "Goodbye, #{name}!"
331
+ }
332
+ defn(:greet, _, _) { |_, name|
333
+ "Hello, #{name}!"
334
+ }
335
+ end
336
+ ```
337
+
338
+ #### Constructor Overloading
339
+
340
+ ```ruby
341
+ require 'functional/pattern_matching'
342
+
343
+ class Foo
344
+ include PatternMatching
345
+
346
+ defn(:initialize) { @name = 'baz' }
347
+ defn(:initialize, _) {|name| @name = name.to_s }
348
+ end
349
+ ```
350
+
351
+ #### Matching by Class/Datatype
352
+
353
+ ```ruby
354
+ require 'functional/pattern_matching'
355
+
356
+ class Foo
357
+ include PatternMatching
358
+
359
+ defn(:concat, Integer, Integer) { |first, second|
360
+ first + second
361
+ }
362
+ defn(:concat, Integer, String) { |first, second|
363
+ "#{first} #{second}"
364
+ }
365
+ defn(:concat, String, String) { |first, second|
366
+ first + second
367
+ }
368
+ defn(:concat, Integer, _) { |first, second|
369
+ first + second.to_i
370
+ }
371
+ end
372
+ ```
373
+
374
+ #### Matching a Hash Parameter
375
+
376
+ ```ruby
377
+ require 'functional/pattern_matching'
378
+
379
+ class Foo
380
+ include PatternMatching
381
+
382
+ defn(:hashable, {foo: :bar}) { |opts|
383
+ # matches any hash with key :foo and value :bar
384
+ :foo_bar
385
+ }
386
+ defn(:hashable, {foo: _, bar: _}) { |f, b|
387
+ # matches any hash with keys :foo and :bar
388
+ # passes the values associated with those keys to the block
389
+ [f, b]
390
+ }
391
+ defn(:hashable, {foo: _}) { |f|
392
+ # matches any hash with key :foo
393
+ # passes the value associated with that key to the block
394
+ # must appear AFTER the prior match or it will override that one
395
+ f
396
+ }
397
+ defn(:hashable, {}) { ||
398
+ # matches an empty hash
399
+ :empty
400
+ }
401
+ defn(:hashable, _) { |opts|
402
+ # matches any hash (or any other value)
403
+ opts
404
+ }
405
+ end
406
+
407
+ ...
408
+
409
+ foo.hashable({foo: :bar}) #=> :foo_bar
410
+ foo.hashable({foo: :baz}) #=> :baz
411
+ foo.hashable({foo: 1, bar: 2}) #=> [1, 2]
412
+ foo.hashable({foo: 1, baz: 2}) #=> 1
413
+ foo.hashable({bar: :baz}) #=> {bar: :baz}
414
+ foo.hashable({}) #=> :empty
415
+ ```
416
+
417
+ #### Variable Length Argument Lists with ALL
418
+
419
+ ```ruby
420
+ defn(:all, :one, ALL) { |args|
421
+ args
422
+ }
423
+ defn(:all, :one, Integer, ALL) { |int, args|
424
+ [int, args]
425
+ }
426
+ defn(:all, 1, _, ALL) { |var, args|
427
+ [var, args]
428
+ }
429
+ defn(:all, ALL) { | args|
430
+ args
431
+ }
432
+
433
+ ...
434
+
435
+ foo.all(:one, 'a', 'bee', :see) #=> ['a', 'bee', :see]
436
+ foo.all(:one, 1, 'bee', :see) #=> [1, 'bee', :see]
437
+ foo.all(1, 'a', 'bee', :see) #=> ['a', ['bee', :see]]
438
+ foo.all('a', 'bee', :see) #=> ['a', 'bee', :see]
439
+ foo.all() #=> NoMethodError: no method `all` matching [] found for class Foo
440
+ ```
441
+
442
+ #### Guard Clauses
443
+
444
+ These examples are based on [Syntax in defnctions: Pattern Matching](http://learnyousomeerlang.com/syntax-in-defnctions)
445
+ in [Learn You Some Erlang for Great Good!](http://learnyousomeerlang.com/).
446
+
447
+ Erlang:
448
+
449
+ ```erlang
450
+ old_enough(X) when X >= 16 -> true;
451
+ old_enough(_) -> false.
452
+
453
+ right_age(X) when X >= 16, X =< 104 ->
454
+ true;
455
+ right_age(_) ->
456
+ false.
457
+
458
+ wrong_age(X) when X < 16; X > 104 ->
459
+ true;
460
+ wrong_age(_) ->
461
+ false.
462
+ ```
463
+
464
+ ```ruby
465
+ defn(:old_enough, _){ true }.when{|x| x >= 16 }
466
+ defn(:old_enough, _){ false }
467
+
468
+ defn(:right_age, _) {
469
+ true
470
+ }.when{|x| x >= 16 && x <= 104 }
471
+
472
+ defn(:right_age, _) {
473
+ false
474
+ }
475
+
476
+ defn(:wrong_age, _) {
477
+ false
478
+ }.when{|x| x < 16 || x > 104 }
479
+
480
+ defn(:wrong_age, _) {
481
+ true
482
+ }
483
+ ```
484
+
485
+ ## Copyright
486
+
487
+ *Functional Ruby* is Copyright &copy; 2013 [Jerry D'Antonio](https://twitter.com/jerrydantonio).
488
+ It is free software and may be redistributed under the terms specified in the LICENSE file.
489
+
490
+ ## License
491
+
492
+ Released under the MIT license.
493
+
494
+ http://www.opensource.org/licenses/mit-license.php
495
+
496
+ > Permission is hereby granted, free of charge, to any person obtaining a copy
497
+ > of this software and associated documentation files (the "Software"), to deal
498
+ > in the Software without restriction, including without limitation the rights
499
+ > to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
500
+ > copies of the Software, and to permit persons to whom the Software is
501
+ > furnished to do so, subject to the following conditions:
502
+ >
503
+ > The above copyright notice and this permission notice shall be included in
504
+ > all copies or substantial portions of the Software.
505
+ >
506
+ > THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
507
+ > IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
508
+ > FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
509
+ > AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
510
+ > LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
511
+ > OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
512
+ > THE SOFTWARE.