egison 0.5.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 94a489dfeb3722cf74e46e867076fec46fb389b7
4
- data.tar.gz: 9b115c122986dd02864a4b25a7754273f4eadd9d
3
+ metadata.gz: 4220d772a26fbea06a65175e59f77466ef5696b2
4
+ data.tar.gz: 4c6a23d914dcd4a1c3c4c74f2b36258fce0c24ec
5
5
  SHA512:
6
- metadata.gz: 896c6d1ad74e28517083ae6cfea6465895f1af804c5fbf51da7c291b51f16effdc120e0a50e5325b61273490e71ebd71b1e46924e3eb34ff2906c0eca2cd12f6
7
- data.tar.gz: bb189940c54dcb19358b5d30b2e94b48d3e262fb2ec22f0c6e7e28299a0ed2853f50e935090f0f45d70266b82e351bfab15e7cdde854e87c4422b752c3aaf7ef
6
+ metadata.gz: 42cb47d6867e69defec1a397afbb0f5df6bfe75ed4182ca66496a1248a2c863bd486f9e13b4a5b8834ebcf85af7b29ba06cb9e08c4e21bfd2ed8219752fa05db
7
+ data.tar.gz: 5db2fa350525a714a6e514b3195a06f4adc0791cf664b92727e258956b5cf19fb24f2c4f2edf2703796693397cef633b07b5f7b8ca6811b7691e4d2c6a30d013
data/README.md CHANGED
@@ -253,16 +253,45 @@ p twin_primes.take(10)
253
253
  #=>[[3, 5], [5, 7], [11, 13], [17, 19], [29, 31], [41, 43], [59, 61], [71, 73], [101, 103], [107, 109]]
254
254
  ```
255
255
 
256
+ ### Algebraic Data Types
257
+
258
+ We can also patten match against algebraic data types as ordinary functional programming languages.
259
+ Here is a simple example.
260
+ Note that, the object in the pattern matches if the target object is equal with it.
261
+
262
+ ```
263
+ class User < Struct.new(:name, :gender, :married, :doctor, :professor)
264
+ def greet
265
+ match(self) do
266
+ with(_[_name, _, _, _, true]) { "Hello, Prof. #{name}!" }
267
+ with(_[_name, _, _, true, _]) { "Hello, Dr. #{name}!" }
268
+ with(_[_name, :male, _, _, _]) { "Hello, Mr. #{name}!" }
269
+ with(_[_name, :female, true, _, _]) { "Hello, Mrs. #{name}!" }
270
+ with(_[_name, :female, _, _, _]) { "Hello, Ms. #{name}!" }
271
+ with(_[_name, _, _, _, _]) { "Hello, #{name}!" }
272
+ end
273
+ end
274
+ end
275
+
276
+ u1 = User.new("Egi", :male, true, false, false)
277
+ p(u1.greet)#=>"Hello, Mr. Egi!"
278
+
279
+ u2 = User.new("Nanaka", :girl, false, false, false)
280
+ p(u2.greet)#=>"Hello, Nanaka!"
281
+
282
+ u3 = User.new("Hirai", :male, true, true, false)
283
+ p(u3.greet)#=>"Hello, Dr. Hirai!"
284
+
285
+ u4 = User.new("Hagiya", :male, true, true, true)
286
+ p(u4.greet)#=>"Hello, Prof. Hagiya!"
287
+ ```
288
+
256
289
  You can find more demonstrations in the [`sample`](https://github.com/egison/egison-ruby/tree/master/sample) directory.
257
290
 
258
291
  ## About Egison
259
292
 
260
- If you get to love the above pattern-matching, please try [the Egison programming language](http://www.egison.org), too.
261
- <<<<<<< HEAD
293
+ If you get to love the above pattern-matching, please try [the Egison programming language](https://github.com/egison/egison), too.
262
294
  Egison is the pattern-matching oriented, purely functional programming language.
263
- =======
264
- Egison is the pattern-matching oriented purely functional programming language.
265
- >>>>>>> 39ede8d0f3300244c240fce2d8069dda3a2f065e
266
295
  Actually, the original pattern-matching system of Egison is more powerful.
267
296
  For example, we can do following things in the original Egison.
268
297
 
@@ -1,5 +1,4 @@
1
1
  require 'egison/version'
2
- # require 'continuation'
3
2
  require 'egison/lazyarray'
4
3
 
5
4
  module PatternMatch
@@ -140,6 +139,7 @@ module PatternMatch
140
139
  end
141
140
 
142
141
  def match(tgt, bindings)
142
+ tgt = tgt.to_a
143
143
  if subpatterns.empty?
144
144
  if tgt.empty?
145
145
  return [[[], []]]
@@ -149,22 +149,33 @@ module PatternMatch
149
149
  else
150
150
  subpatterns = @subpatterns.clone
151
151
  px = subpatterns.shift
152
- if px.quantified
153
- if subpatterns.empty?
154
- [[[[px.pattern, tgt]], []]]
152
+ if px.kind_of?(Pattern)
153
+ if px.quantified
154
+ if subpatterns.empty?
155
+ [[[[px.pattern, tgt]], []]]
156
+ else
157
+ unjoineds = @matcher.unjoin(tgt)
158
+ unjoineds.map do |xs, ys|
159
+ [[[px.pattern, xs], [PatternWithMatcher.new(@matcher, *subpatterns), ys]], []]
160
+ end
161
+ end
155
162
  else
156
- unjoineds = @matcher.unjoin(tgt)
157
- unjoineds.map do |xs, ys|
158
- [[[px.pattern, xs], [PatternWithMatcher.new(@matcher, *subpatterns), ys]], []]
163
+ if tgt.empty?
164
+ []
165
+ else
166
+ unconseds = @matcher.uncons(tgt)
167
+ unconseds.map do |x, xs|
168
+ [[[px, x], [PatternWithMatcher.new(@matcher, *subpatterns), xs]], []]
169
+ end
159
170
  end
160
171
  end
161
172
  else
162
173
  if tgt.empty?
163
174
  []
164
175
  else
165
- unconseds = @matcher.uncons(tgt)
176
+ unconseds = @matcher.uncons(tgt).select { |x, xs| px == x }
166
177
  unconseds.map do |x, xs|
167
- [[[px, x], [PatternWithMatcher.new(@matcher, *subpatterns), xs]], []]
178
+ [[[PatternWithMatcher.new(@matcher, *subpatterns), xs]], []]
168
179
  end
169
180
  end
170
181
  end
@@ -179,18 +190,28 @@ module PatternMatch
179
190
  else
180
191
  subpatterns = @subpatterns.clone
181
192
  px = subpatterns.shift
182
- if px.quantified
183
- if subpatterns.empty?
184
- block.([[[px.pattern, tgt]], []])
193
+ if px.kind_of?(Pattern)
194
+ if px.quantified
195
+ if subpatterns.empty?
196
+ block.([[[px.pattern, tgt]], []])
197
+ else
198
+ @matcher.unjoin_stream(tgt) do |xs, ys|
199
+ block.([[px.pattern, xs], [PatternWithMatcher.new(@matcher, *subpatterns), ys]], [])
200
+ end
201
+ end
185
202
  else
186
- @matcher.unjoin_stream(tgt) do |xs, ys|
187
- block.([[px.pattern, xs], [PatternWithMatcher.new(@matcher, *subpatterns), ys]], [])
203
+ unless tgt.empty?
204
+ @matcher.uncons_stream(tgt) do |x, xs|
205
+ block.([[px, x], [PatternWithMatcher.new(@matcher, *subpatterns), xs]], [])
206
+ end
188
207
  end
189
208
  end
190
209
  else
191
210
  unless tgt.empty?
192
211
  @matcher.uncons_stream(tgt) do |x, xs|
193
- block.([[px, x], [PatternWithMatcher.new(@matcher, *subpatterns), xs]], [])
212
+ if px == x
213
+ block.([[PatternWithMatcher.new(@matcher, *subpatterns), xs]], [])
214
+ end
194
215
  end
195
216
  end
196
217
  end
@@ -311,7 +332,7 @@ module PatternMatch
311
332
  def method_missing(name, *args)
312
333
  ::Kernel.raise ::ArgumentError, "wrong number of arguments (#{args.length} for 0)" unless args.empty?
313
334
  if /^__/.match(name.to_s)
314
- ValuePattern.new(@ctx, name.to_s.gsub(/^__/, "").gsub("_plus_", "+").gsub("_minus_", "-"))
335
+ ValuePattern.new(@ctx, name.to_s.gsub(/^__/, ""))
315
336
  elsif /^_/.match(name.to_s)
316
337
  PatternVariable.new(name.to_s.gsub(/^_/, "").to_sym)
317
338
  else
@@ -393,13 +414,22 @@ module PatternMatch
393
414
  def with(pat, &block)
394
415
  ctx = @ctx
395
416
  tgt = @tgt
396
- mstack = MatchingStateStack.new(pat,tgt)
397
- mstack.match
398
- if mstack.results.empty?
399
- nil
417
+ if pat.kind_of?(Pattern)
418
+ mstack = MatchingStateStack.new(pat,tgt)
419
+ mstack.match
420
+ if mstack.results.empty?
421
+ nil
422
+ else
423
+ ret = with_bindings(ctx, mstack.results.first, &block)
424
+ ::Kernel.throw(:exit_match, ret)
425
+ end
400
426
  else
401
- ret = with_bindings(ctx, mstack.results.first, &block)
402
- ::Kernel.throw(:exit_match, ret)
427
+ if pat == tgt
428
+ ret = with_bindings(ctx, [], &block)
429
+ ::Kernel.throw(:exit_match, ret)
430
+ else
431
+ nil
432
+ end
403
433
  end
404
434
  rescue PatternNotMatch
405
435
  end
@@ -14,10 +14,6 @@ class Class
14
14
 
15
15
  private
16
16
 
17
- def accept_array_only(val)
18
- raise PatternMatch::PatternNotMatch unless val.kind_of?(Array)
19
- end
20
-
21
17
  def test_conv_lazy_array(val)
22
18
  raise PatternMatch::PatternNotMatch unless val.respond_to?(:each)
23
19
  Egison::LazyArray.new(val)
@@ -26,13 +22,12 @@ end
26
22
 
27
23
  module Egison
28
24
  extend self
29
-
25
+
30
26
  class List
31
27
  end
32
28
 
33
29
  class << List
34
30
  def uncons(val)
35
- accept_array_only(val)
36
31
  val2 = val.clone
37
32
  x = val2.shift
38
33
  [[x, val2]]
@@ -48,7 +43,6 @@ module Egison
48
43
  end
49
44
 
50
45
  def unjoin(val)
51
- accept_array_only(val)
52
46
  val2 = val.clone
53
47
  xs = []
54
48
  ys = val2.clone
@@ -11,7 +11,6 @@ module Egison
11
11
 
12
12
  class << Multiset
13
13
  def uncons(val)
14
- accept_array_only(val)
15
14
  match_all(val) do
16
15
  with(List.(*_hs, _x, *_ts)) do
17
16
  [x, hs + ts]
@@ -32,7 +31,6 @@ module Egison
32
31
  end
33
32
 
34
33
  def unjoin(val)
35
- accept_array_only(val)
36
34
  val2 = val.clone
37
35
  xs = []
38
36
  ys = val2.clone
@@ -69,7 +67,6 @@ module Egison
69
67
 
70
68
  class << Set
71
69
  def uncons(val)
72
- accept_array_only(val)
73
70
  match_all(val) do
74
71
  with(List.(*_, _x, *_)) do
75
72
  [x, val]
@@ -90,7 +87,6 @@ module Egison
90
87
  end
91
88
 
92
89
  def unjoin(val)
93
- accept_array_only(val)
94
90
  val2 = val.clone
95
91
  xs = []
96
92
  ys = val2.clone
@@ -1,3 +1,3 @@
1
1
  module Egison
2
- VERSION = "0.5.0"
2
+ VERSION = "0.6.0"
3
3
  end
@@ -0,0 +1,15 @@
1
+ require 'egison'
2
+
3
+ include Egison
4
+
5
+ def fib (n)
6
+ match(n) do
7
+ with(0) { 0 }
8
+ with(1) { 1 }
9
+ with(_) { fib(n - 1) + fib(n - 2) }
10
+ end
11
+ end
12
+
13
+ p(fib(0))
14
+ p(fib(1))
15
+ p(fib(10))
@@ -0,0 +1,28 @@
1
+ require 'egison'
2
+
3
+ include Egison
4
+
5
+ class User < Struct.new(:name, :gender, :married, :doctor, :professor)
6
+ def greet
7
+ match(self) do
8
+ with(_[_name, _, _, _, true]) { "Hello, Prof. #{name}!" }
9
+ with(_[_name, _, _, true, _]) { "Hello, Dr. #{name}!" }
10
+ with(_[_name, :male, _, _, _]) { "Hello, Mr. #{name}!" }
11
+ with(_[_name, :female, true, _, _]) { "Hello, Mrs. #{name}!" }
12
+ with(_[_name, :female, _, _, _]) { "Hello, Ms. #{name}!" }
13
+ with(_[_name, _, _, _, _]) { "Hello, #{name}!" }
14
+ end
15
+ end
16
+ end
17
+
18
+ u1 = User.new("Egi", :male, true, false, false)
19
+ p(u1.greet)
20
+
21
+ u2 = User.new("Nanaka", :girl, false, false, false)
22
+ p(u2.greet)
23
+
24
+ u3 = User.new("Hirai", :male, true, true, false)
25
+ p(u3.greet)
26
+
27
+ u4 = User.new("Hagiya", :male, true, true, true)
28
+ p(u4.greet)
@@ -4,6 +4,9 @@ include Egison
4
4
 
5
5
  def poker_hands cs
6
6
  match(cs) do
7
+ with(Multiset.(_[_s, 10], _[__s, 11], _[__s, 12], _[__s, 13], _[__s, 1])) do
8
+ "Royal Straight flush"
9
+ end
7
10
  with(Multiset.(_[_s, _n], _[__s, __("n+1")], _[__s, __("n+2")], _[__s, __("n+3")], _[__s, __("n+4")])) do
8
11
  "Straight flush"
9
12
  end
@@ -34,6 +37,7 @@ def poker_hands cs
34
37
  end
35
38
  end
36
39
 
40
+ p(poker_hands([["diamond", 1], ["diamond", 10], ["diamond", 13], ["diamond", 12], ["diamond", 11]])) #=> "Straight flush"
37
41
  p(poker_hands([["diamond", 1], ["diamond", 3], ["diamond", 5], ["diamond", 4], ["diamond", 2]])) #=> "Straight flush"
38
42
  p(poker_hands([["diamond", 1], ["club", 2], ["club", 1], ["heart", 1], ["diamond", 2]])) #=> "Full house"
39
43
  p(poker_hands([["diamond", 4], ["club", 2], ["club", 5], ["heart", 1], ["diamond", 3]])) #=> "Straight"
@@ -0,0 +1,12 @@
1
+ require 'egison'
2
+ require 'prime'
3
+
4
+ include Egison
5
+
6
+ twin_primes = match_stream(Prime) {
7
+ with(List.(*_, _x, __("x + 2"), *_)) {
8
+ [x, x + 2]
9
+ }
10
+ }
11
+
12
+ p twin_primes.take(10)
@@ -1,17 +1,10 @@
1
1
  require 'egison'
2
- require 'prime'
3
2
 
4
3
  include Egison
5
4
 
6
5
  p(match_stream(1..5){ with(List.(*_, _x, *_, _y, *_)) { [x, y] } }.to_a)
7
6
 
8
- twin_primes = match_stream(Prime) {
9
- with(List.(*_, _x, __("x + 2"), *_)) {
10
- [x, x + 2]
11
- }
12
- }
13
-
14
- p twin_primes.take(10)
7
+ p(match_stream(1..5){ with(List.(*_, 2, *_, _y, *_)) { [2, y] } }.to_a)
15
8
 
16
9
  def nats
17
10
  (1..Float::INFINITY)
@@ -0,0 +1,39 @@
1
+ require 'spec_helper'
2
+ require 'egison'
3
+
4
+ include Egison
5
+
6
+ class User < Struct.new(:name, :gender, :married, :doctor, :professor)
7
+ def greet
8
+ match(self) do
9
+ with(_[_name, _, _, _, true]) { "Hello, Prof. #{name}!" }
10
+ with(_[_name, _, _, true, _]) { "Hello, Dr. #{name}!" }
11
+ with(_[_name, :male, _, _, _]) { "Hello, Mr. #{name}!" }
12
+ with(_[_name, :female, true, _, _]) { "Hello, Mrs. #{name}!" }
13
+ with(_[_name, :female, _, _, _]) { "Hello, Ms. #{name}!" }
14
+ with(_[_name, _, _, _, _]) { "Hello, #{name}!" }
15
+ end
16
+ end
17
+ end
18
+
19
+ describe "sample" do
20
+ describe "greet.rb" do
21
+ it %q{User.new("Egi", :male, true, false, false).greet} do
22
+ expect(User.new("Egi", :male, true, false, false).greet).to eq \
23
+ "Hello, Mr. Egi!"
24
+ end
25
+ it %q{User.new("Nanaka", :girl, false, false, false).greet} do
26
+ expect(User.new("Nanaka", :girl, false, false, false).greet).to eq \
27
+ "Hello, Nanaka!"
28
+ end
29
+ it %q{User.new("Hirai", :male, true, true, false).greet} do
30
+ expect(User.new("Hirai", :male, true, true, false).greet).to eq \
31
+ "Hello, Dr. Hirai!"
32
+ end
33
+ it %q{User.new("Hagiya", :male, true, true, true).greet} do
34
+ expect(User.new("Hagiya", :male, true, true, true).greet).to eq \
35
+ "Hello, Prof. Hagiya!"
36
+ end
37
+ end
38
+ end
39
+
@@ -0,0 +1,31 @@
1
+ require 'spec_helper'
2
+ require 'egison'
3
+ require 'prime'
4
+
5
+ include Egison
6
+
7
+ def twin_primes
8
+ match_stream(Prime) {
9
+ with(List.(*_, _x, __("x + 2"), *_)) {
10
+ [x, x + 2]
11
+ }
12
+ }
13
+ end
14
+
15
+ describe "sample" do
16
+ describe "prime.rb" do
17
+
18
+ it %q{twin_primes.take(10)} do
19
+ expect(twin_primes.take(10)).to eq \
20
+ [[3, 5], [5, 7], [11, 13], [17, 19], [29, 31], [41, 43], [59, 61], [71, 73], [101, 103], [107, 109]]
21
+ end
22
+
23
+ # assign to a variable, execute twice (or more), then obtain the same results. (for twin-primes)
24
+ it %q{assign to a variable, execute twice (or more), then obtain the same results. (for twin-primes)} do
25
+ tp = twin_primes
26
+ tp.take(10) # discard
27
+ expect(tp.take(10)).to eq \
28
+ [[3, 5], [5, 7], [11, 13], [17, 19], [29, 31], [41, 43], [59, 61], [71, 73], [101, 103], [107, 109]]
29
+ end
30
+ end
31
+ end
@@ -1,17 +1,8 @@
1
1
  require 'spec_helper'
2
2
  require 'egison'
3
- require 'prime'
4
3
 
5
4
  include Egison
6
5
 
7
- def twin_primes
8
- match_stream(Prime) {
9
- with(List.(*_, _x, __("x + 2"), *_)) {
10
- [x, x + 2]
11
- }
12
- }
13
- end
14
-
15
6
  def nats
16
7
  (1..Float::INFINITY)
17
8
  end
@@ -23,11 +14,6 @@ describe "sample" do
23
14
  [[1, 2], [1, 3], [2, 3], [1, 4], [2, 4], [3, 4], [1, 5], [2, 5], [3, 5], [4, 5]]
24
15
  end
25
16
 
26
- it %q{twin_primes.take(10)} do
27
- expect(twin_primes.take(10)).to eq \
28
- [[3, 5], [5, 7], [11, 13], [17, 19], [29, 31], [41, 43], [59, 61], [71, 73], [101, 103], [107, 109]]
29
- end
30
-
31
17
  # (take 10 (match-all nats (multiset integer) [<cons $m <cons $n _>> [m n]]))
32
18
  it %q{match_stream(nats){ with(Multiset.(_m, _n, *_)) { [m, n] } }.take(10)} do
33
19
  expect(match_stream(nats){ with(Multiset.(_m, _n, *_)) { [m, n] } }.take(10)).to eq \
@@ -53,13 +39,5 @@ describe "sample" do
53
39
  [[1, 1], [1, 2], [2, 1], [1, 3], [2, 2], [3, 1], [1, 4], [2, 3], [3, 2], [4, 1],
54
40
  [1, 5], [2, 4], [3, 3], [4, 2], [5, 1], [1, 6], [2, 5], [3, 4], [4, 3], [5, 2]]
55
41
  end
56
-
57
- # assign to a variable, execute twice (or more), then obtain the same results. (for twin-primes)
58
- it %q{assign to a variable, execute twice (or more), then obtain the same results. (for twin-primes)} do
59
- tp = twin_primes
60
- tp.take(10) # discard
61
- expect(tp.take(10)).to eq \
62
- [[3, 5], [5, 7], [11, 13], [17, 19], [29, 31], [41, 43], [59, 61], [71, 73], [101, 103], [107, 109]]
63
- end
64
42
  end
65
43
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: egison
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Satoshi Egi
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-07-22 00:00:00.000000000 Z
11
+ date: 2014-07-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -74,17 +74,22 @@ files:
74
74
  - lib/egison/matcher.rb
75
75
  - lib/egison/version.rb
76
76
  - sample/combination.rb
77
+ - sample/fib.rb
78
+ - sample/greet.rb
77
79
  - sample/join.rb
78
80
  - sample/poker_hands.rb
81
+ - sample/primes.rb
79
82
  - sample/set.rb
80
83
  - sample/stream.rb
81
84
  - spec/lib/egison/core_spec.rb
82
85
  - spec/lib/egison/matcher_spec.rb
83
86
  - spec/lib/egison_spec.rb
84
87
  - spec/sample/combination_spec.rb
88
+ - spec/sample/greet_spec.rb
85
89
  - spec/sample/join_spec.rb
86
90
  - spec/sample/join_stream_spec.rb
87
91
  - spec/sample/poker_hands_spec.rb
92
+ - spec/sample/prime_spec.rb
88
93
  - spec/sample/set_spec.rb
89
94
  - spec/sample/stream_spec.rb
90
95
  - spec/spec_helper.rb