egison 0.5.0 → 0.6.0

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.
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