patternmatching 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,162 @@
1
+ require File.dirname(__FILE__) + '/spec_helper.rb'
2
+ require 'patternmatching'
3
+
4
+ class CalcM
5
+ # At first, extends with the module
6
+ extend PatternMatching
7
+
8
+ # def calcm(o), as 3 partial styles
9
+ func(:calcm).seems as {plus(:left, :right)} do
10
+ calcm(left) + calcm(right)
11
+ end
12
+ func(:calcm).seems as {mul(:left, :right)} do
13
+ calcm(left) * calcm(right)
14
+ end
15
+ func(:calcm).seems as {:value} do
16
+ value
17
+ end
18
+ end
19
+
20
+ class CalcX
21
+ extend PatternMatching
22
+
23
+ func(:calcx) do
24
+ seems as {plus(:left, :right)} do
25
+ calcx(left) + calcx(right)
26
+ end
27
+ seems as {mul(:left, :right)} do
28
+ calcx(left) * calcx(right)
29
+ end
30
+ end
31
+ func(:calcx).seems as {:value} do
32
+ value
33
+ end
34
+ end
35
+
36
+ class Person
37
+ def initialize(name, age)
38
+ @name = name
39
+ @age = age
40
+ end
41
+ attr :name
42
+ attr :age
43
+ end
44
+
45
+ include PatternMatching
46
+ def calc(code)
47
+ make(code) {
48
+ seems as {plus(:a, :b)} do calc(a) + calc(b) end
49
+ seems as {mul(:a, :b)} do calc(a) * calc(b) end
50
+ seems something do code end
51
+ }
52
+ end
53
+
54
+ describe "PatternMatching from Example" do
55
+ it "shuold run calcm as a regular method." do
56
+ code = PatternMatching.build {plus(mul(100, 100), 200)}
57
+ ret = CalcM.new.calcm(code)
58
+ ret.should == 10200
59
+ end
60
+
61
+ it "shuold run calcx as a regular method." do
62
+ code = PatternMatching.build {plus(mul(100, 100), 200)}
63
+ ret = CalcX.new.calcx(code)
64
+ ret.should == 10200
65
+ end
66
+
67
+ it "should run calc as a regular function." do
68
+ code = PatternMatching.build {plus(mul(100, 100), 200)}
69
+ ret = calc(code)
70
+ ret.should == 10200
71
+ end
72
+
73
+ it "should look Enumerable pattern." do
74
+ is = build { exact([1,2,3,4,5]) }
75
+ result = make is do
76
+ seems as {exact([:a,:b,:c])} do # not match
77
+ a.to_s + " and " + b.to_s + " and" + c.to_s
78
+ end
79
+ seems as {exact([:a,:b, _!(:c)])} do
80
+ a.to_s + ", " + b.to_s + " and " + c.to_s
81
+ end
82
+ seems something do
83
+ "not matched"
84
+ end
85
+ end
86
+ result.should == "1, 2 and 345"
87
+ end
88
+
89
+ it "should look Just Enumerable pattern." do
90
+ is = build { exact([1,2,3,4,5]) }
91
+ result = make is do
92
+ seems as {exact([:a,:b,:c])} do # not match
93
+ a.to_s + " and " + b.to_s + " and" + c.to_s
94
+ end
95
+ seems as {exact([:a,:b, :c, :d, :e])} do
96
+ a.to_s + ", " + b.to_s + ", " + c.to_s + ", " + d.to_s + ", " + e.to_s
97
+ end
98
+ seems something do
99
+ "not matched"
100
+ end
101
+ end
102
+ result.should == "1, 2, 3, 4, 5"
103
+ end
104
+
105
+ it "should look Hash pattern." do
106
+ dict = build { {:name => "Taro", :age => 5} }
107
+ result = make dict do
108
+ seems as {{:name => :name}} do
109
+ "He is " + name
110
+ end
111
+ seems something do
112
+ "no name"
113
+ end
114
+ end
115
+ result.should == "He is Taro"
116
+ end
117
+
118
+ it "should look non-Hash pattern." do
119
+ person = Person.new("Jiro", 3)
120
+ result = make person do
121
+ seems as {{:name => :name}} do
122
+ "He is " + name
123
+ end
124
+ seems something do
125
+ "no name"
126
+ end
127
+ end
128
+ result.should == "He is Jiro"
129
+ end
130
+
131
+ it "should look nested pattern." do
132
+ code = build {plus(mul(100, 120, 300), plus(200, 150))}
133
+ result = make code do
134
+ seems as {plus(plus(:a, :b, _), plus(:c, _))} do # not match
135
+ [a, b, c]
136
+ end
137
+ seems as {plus(mul(_, :a, _), plus(:b, _))} do
138
+ [a, b]
139
+ end
140
+ seems something do
141
+ nil
142
+ end
143
+ end
144
+ result.should == [120, 200]
145
+ end
146
+
147
+ it "should look wildcard node pattern." do
148
+ code = build {plus(mul(100, 120, 300), plus(200, 150))}
149
+ result = make code do
150
+ seems as {_(_(_, _, :a), mul(_, :b))} do # not match
151
+ [a, b]
152
+ end
153
+ seems as {plus(_(_, :a, _), _(:b, _))} do
154
+ [a, b]
155
+ end
156
+ seems something do
157
+ nil
158
+ end
159
+ end
160
+ result.should == [120, 200]
161
+ end
162
+ end
data/spec/spec.opts ADDED
@@ -0,0 +1 @@
1
+ --colour
@@ -0,0 +1 @@
1
+ require 'spec'
@@ -0,0 +1,231 @@
1
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
2
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
3
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
4
+ <head>
5
+ <link rel="stylesheet" href="stylesheets/screen.css" type="text/css" media="screen" />
6
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
7
+ <title>
8
+ PatternMatching module
9
+ </title>
10
+ <script src="javascripts/rounded_corners_lite.inc.js" type="text/javascript"></script>
11
+ <style>
12
+
13
+ </style>
14
+ <script type="text/javascript">
15
+ window.onload = function() {
16
+ settings = {
17
+ tl: { radius: 10 },
18
+ tr: { radius: 10 },
19
+ bl: { radius: 10 },
20
+ br: { radius: 10 },
21
+ antiAlias: true,
22
+ autoPad: true,
23
+ validTags: ["div"]
24
+ }
25
+ var versionBox = new curvyCorners(settings, document.getElementById("version"));
26
+ versionBox.applyCornersToAll();
27
+ }
28
+ </script>
29
+ </head>
30
+ <body>
31
+ <div id="main">
32
+
33
+ <h1>PatternMatching module</h1>
34
+ <div id="version" class="clickable" onclick='document.location = "http://rubyforge.org/projects/patternmatching"; return false'>
35
+ Get Version
36
+ <a href="http://rubyforge.org/projects/patternmatching" class="numbers">0.1.0</a>
37
+ </div>
38
+ <h1>&#x2192; &#8216;patternmatching&#8217;</h1>
39
+
40
+
41
+ <h2>What</h2>
42
+
43
+
44
+ Provides a pure ruby module that:
45
+ <ul>
46
+ <li>can build structured objects easily</li>
47
+ <li>can enable pattern match of objects</li>
48
+ <li>can define method as a partial function style</li>
49
+ </ul>
50
+
51
+
52
+ <h2>Installing</h2>
53
+
54
+
55
+ <pre syntax="ruby">sudo gem install patternmatching</pre>
56
+
57
+ <h2>The basics</h2>
58
+
59
+
60
+ <p>This module provides methods for tree pattern matching features.</p>
61
+
62
+
63
+ <ul>
64
+ <li>For detail, see Wikipedia: <a href="http://en.wikipedia.org/wiki/Pattern_matching">Pattern matching</a></li>
65
+ <li>Syntax based on meta-programming, like &#8220;rspec&#8221;, and so on.</li>
66
+ </ul>
67
+
68
+
69
+ <p>Note: Default equivalence used in structured pattern matching is
70
+ based on &#8220;pattern === data&#8221;, so &#8220;foo(Numeric)&#8221; matches with &#8220;foo(100)&#8221;</p>
71
+
72
+
73
+ <p>Note: Not thread safe now.</p>
74
+
75
+
76
+ <h2>Demonstration of usage</h2>
77
+
78
+
79
+ <h3>Pattern matching expression</h3>
80
+ <pre>
81
+ require "patternmatching"
82
+
83
+ # For DSL style code, include PatternMatching
84
+ include PatternMatching
85
+
86
+ # match example
87
+ def calc(code)
88
+ make(code) {
89
+ seems as {plus(:x, :y)} do calc(x) + calc(y) end
90
+ seems as {mul(:x, :y)} do calc(x) * calc(y) end
91
+ seems something do code end
92
+ }
93
+ end
94
+
95
+ code = build {plus(mul(100, 100), 200)}
96
+ p calc(code) #=&gt; 10200
97
+ </pre>
98
+
99
+ <h3>Partial style method</h3>
100
+ <pre>
101
+ require "patternmatching"
102
+
103
+ # Structured data builder
104
+ code = PatternMatching.build {plus(mul(100, 100), 200)}
105
+
106
+ # Partial style method example
107
+ class Calc
108
+ # At first, extends with the module
109
+ extend PatternMatching
110
+
111
+ # def calcm(o), as 3 partial styles
112
+ func(:calcm).seems as {plus(:x, :y)} do
113
+ calcm(x) + calcm(y)
114
+ end
115
+ func(:calcm).seems as {mul(:x, :y)} do
116
+ calcm(x) * calcm(y)
117
+ end
118
+ func(:calcm).seems as {:value} do
119
+ value
120
+ end
121
+ end
122
+
123
+ # use as standard method
124
+ p Calc.new.calcm(code) #=&gt; 10200
125
+ </pre>
126
+
127
+ <h3>Array/Enumerable pattern</h3>
128
+ <pre>
129
+ require "patternmatching"
130
+
131
+ include PatternMatching
132
+
133
+ # Example for matching Enumerable
134
+ is = build { exact([1,2,3,4,5]) }
135
+ make is do
136
+ # _! matches rest of lists
137
+ seems as {exact([:a,:b, _!(:c)])} do
138
+ puts a.to_s + ", " + b.to_s + " and " + c.to_s
139
+ end
140
+ seems something do
141
+ puts "not matched"
142
+ end
143
+ end # =&gt; "1, 2, and 345"
144
+ </pre>
145
+
146
+ <h3>Hash pattern</h3>
147
+ <pre>
148
+ require "patternmatching"
149
+
150
+ include PatternMatching
151
+
152
+ # Example for matching Hash
153
+ dict = build { {:name =&gt; "Taro", :age =&gt; 5} }
154
+ make dict do
155
+ seems as {{:name =&gt; :name}} do
156
+ puts "He is " + name
157
+ end
158
+ seems something do
159
+ puts "no name"
160
+ end
161
+ end # =&gt; "He is Taro"
162
+ </pre>
163
+
164
+ <h3>Non-Hash/Object pattern</h3>
165
+ <pre>
166
+ require "patternmatching"
167
+
168
+ include PatternMatching
169
+
170
+ class Person
171
+ def initialize(name, age)
172
+ @name = name
173
+ @age = age
174
+ end
175
+ attr :name
176
+ attr :age
177
+ end
178
+
179
+ # Example for matching Object except Hash
180
+ person = Person.new("Jiro", 3)
181
+ make person do
182
+ seems as {{:name =&gt; :name}} do
183
+ puts "He is " + name
184
+ end
185
+ seems something do
186
+ puts "no name"
187
+ end
188
+ end # =&gt; "He is Jiro"
189
+ </pre>
190
+
191
+ <h2>Forum</h2>
192
+
193
+
194
+ <h2>How to submit patches</h2>
195
+
196
+
197
+ <p>Read the <a href="http://drnicwilliams.com/2007/06/01/8-steps-for-fixing-other-peoples-code/">8 steps for fixing other people&#8217;s code</a> and for section <a href="http://drnicwilliams.com/2007/06/01/8-steps-for-fixing-other-peoples-code/#8b-google-groups">8b: Submit patch to Google Groups</a>, use the Google Group above.</p>
198
+
199
+
200
+ <p>The trunk repository is <code>svn://rubyforge.org/var/svn/patternmatching/trunk</code> for anonymous access.</p>
201
+
202
+
203
+ <h2>License</h2>
204
+
205
+
206
+ <p>This code is free to use under the terms of the <span class="caps">MIT</span> license.</p>
207
+
208
+
209
+ <h2>Link</h2>
210
+
211
+
212
+ <ul>
213
+ <li><a href="http://patternmatching.rubyforge.org/">Web Site</a></li>
214
+ <li><a href="http://rubyforge.org/projects/patternmatching/">Project Page</a></li>
215
+ </ul>
216
+
217
+
218
+ <h2>Contact</h2>
219
+
220
+
221
+ <p>Comments are welcome. Send an email to <a href="mailto:bellbind@gmail.com"><span class="caps">ICHIYAMA</span> Ryoichi</a>. <a href="http://d.hatena.ne.jp/bellbind">My blog</a> (written in Japanese) could be help you.</p>
222
+ <p class="coda">
223
+ <a href="mailto:drnicwilliams@gmail.com">Dr Nic</a>, 4th June 2007<br>
224
+ Theme extended from <a href="http://rb2js.rubyforge.org/">Paul Battley</a>
225
+ </p>
226
+ </div>
227
+
228
+ <!-- insert site tracking codes here, like Google Urchin -->
229
+
230
+ </body>
231
+ </html>
data/website/index.txt ADDED
@@ -0,0 +1,163 @@
1
+ h1. PatternMatching module
2
+
3
+ h1. &#x2192; 'patternmatching'
4
+
5
+ h2. What
6
+
7
+ Provides a pure ruby module that:
8
+ * can build structured objects easily
9
+ * can enable pattern match of objects
10
+ * can define method as a partial function style
11
+
12
+ h2. Installing
13
+
14
+ <pre syntax="ruby">sudo gem install patternmatching</pre>
15
+
16
+ h2. The basics
17
+
18
+ This module provides methods for tree pattern matching features.
19
+
20
+ * For detail, see Wikipedia: "Pattern matching":http://en.wikipedia.org/wiki/Pattern_matching
21
+ * Syntax based on meta-programming, like "rspec", and so on.
22
+
23
+ Note: Default equivalence used in structured pattern matching is
24
+ based on "pattern === data", so "foo(Numeric)" matches with "foo(100)"
25
+
26
+ Note: Not thread safe now.
27
+
28
+ h2. Demonstration of usage
29
+
30
+ <h3>Pattern matching expression</h3>
31
+ <pre>
32
+ require "patternmatching"
33
+
34
+ # For DSL style code, include PatternMatching
35
+ include PatternMatching
36
+
37
+ # match example
38
+ def calc(code)
39
+ make(code) {
40
+ seems as {plus(:x, :y)} do calc(x) + calc(y) end
41
+ seems as {mul(:x, :y)} do calc(x) * calc(y) end
42
+ seems something do code end
43
+ }
44
+ end
45
+
46
+ code = build {plus(mul(100, 100), 200)}
47
+ p calc(code) #=> 10200
48
+ </pre>
49
+
50
+ <h3>Partial style method</h3>
51
+ <pre>
52
+ require "patternmatching"
53
+
54
+ # Structured data builder
55
+ code = PatternMatching.build {plus(mul(100, 100), 200)}
56
+
57
+ # Partial style method example
58
+ class Calc
59
+ # At first, extends with the module
60
+ extend PatternMatching
61
+
62
+ # def calcm(o), as 3 partial styles
63
+ func(:calcm).seems as {plus(:x, :y)} do
64
+ calcm(x) + calcm(y)
65
+ end
66
+ func(:calcm).seems as {mul(:x, :y)} do
67
+ calcm(x) * calcm(y)
68
+ end
69
+ func(:calcm).seems as {:value} do
70
+ value
71
+ end
72
+ end
73
+
74
+ # use as standard method
75
+ p Calc.new.calcm(code) #=> 10200
76
+ </pre>
77
+
78
+ <h3>Array/Enumerable pattern</h3>
79
+ <pre>
80
+ require "patternmatching"
81
+
82
+ include PatternMatching
83
+
84
+ # Example for matching Enumerable
85
+ is = build { exact([1,2,3,4,5]) }
86
+ make is do
87
+ # _! matches rest of lists
88
+ seems as {exact([:a,:b, _!(:c)])} do
89
+ puts a.to_s + ", " + b.to_s + " and " + c.to_s
90
+ end
91
+ seems something do
92
+ puts "not matched"
93
+ end
94
+ end # => "1, 2, and 345"
95
+ </pre>
96
+
97
+ <h3>Hash pattern</h3>
98
+ <pre>
99
+ require "patternmatching"
100
+
101
+ include PatternMatching
102
+
103
+ # Example for matching Hash
104
+ dict = build { {:name => "Taro", :age => 5} }
105
+ make dict do
106
+ seems as {{:name => :name}} do
107
+ puts "He is " + name
108
+ end
109
+ seems something do
110
+ puts "no name"
111
+ end
112
+ end # => "He is Taro"
113
+ </pre>
114
+
115
+ <h3>Non-Hash/Object pattern</h3>
116
+ <pre>
117
+ require "patternmatching"
118
+
119
+ include PatternMatching
120
+
121
+ class Person
122
+ def initialize(name, age)
123
+ @name = name
124
+ @age = age
125
+ end
126
+ attr :name
127
+ attr :age
128
+ end
129
+
130
+ # Example for matching Object except Hash
131
+ person = Person.new("Jiro", 3)
132
+ make person do
133
+ seems as {{:name => :name}} do
134
+ puts "He is " + name
135
+ end
136
+ seems something do
137
+ puts "no name"
138
+ end
139
+ end # => "He is Jiro"
140
+ </pre>
141
+
142
+ h2. Forum
143
+
144
+
145
+ h2. How to submit patches
146
+
147
+ Read the "8 steps for fixing other people's code":http://drnicwilliams.com/2007/06/01/8-steps-for-fixing-other-peoples-code/ and for section "8b: Submit patch to Google Groups":http://drnicwilliams.com/2007/06/01/8-steps-for-fixing-other-peoples-code/#8b-google-groups, use the Google Group above.
148
+
149
+ The trunk repository is <code>svn://rubyforge.org/var/svn/patternmatching/trunk</code> for anonymous access.
150
+
151
+ h2. License
152
+
153
+ This code is free to use under the terms of the MIT license.
154
+
155
+ h2. Link
156
+
157
+ * "Web Site":http://patternmatching.rubyforge.org/
158
+ * "Project Page":http://rubyforge.org/projects/patternmatching/
159
+
160
+ h2. Contact
161
+
162
+ Comments are welcome. Send an email to "ICHIYAMA Ryoichi":mailto:bellbind@gmail.com. "My blog":http://d.hatena.ne.jp/bellbind (written in Japanese) could be help you.
163
+