immutable 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,116 @@
1
+ require_relative "../test_helper"
2
+
3
+ with_tailcall_optimization {
4
+ require_relative "../../lib/immutable/deque"
5
+ }
6
+
7
+ module Immutable
8
+ class TestDeque < Test::Unit::TestCase
9
+ def test_head
10
+ assert_raise(EmptyError) do
11
+ Deque[].head
12
+ end
13
+ assert_equal(1, Deque[1].head)
14
+ assert_equal(1, Deque[1, 2, 3].head)
15
+ end
16
+
17
+ def test_last
18
+ assert_raise(EmptyError) do
19
+ Deque[].last
20
+ end
21
+ assert_equal(1, Deque[1].last)
22
+ assert_equal(3, Deque[1, 2, 3].last)
23
+ end
24
+
25
+ def test_tail
26
+ assert_raise(EmptyError) do
27
+ Deque[].tail
28
+ end
29
+ assert(Deque[1].tail.empty?)
30
+ assert_equal(2, Deque[1, 2].tail.head)
31
+ assert_equal(2, Deque[1, 2, 3].tail.head)
32
+ assert_equal(3, Deque[1, 2, 3].tail.tail.head)
33
+ end
34
+
35
+ def test_init
36
+ assert_raise(EmptyError) do
37
+ Deque[].init
38
+ end
39
+ assert(Deque[1].init.empty?)
40
+ assert_equal(1, Deque[1, 2].init.last)
41
+ assert_equal(2, Deque[1, 2, 3].init.last)
42
+ assert_equal(1, Deque[1, 2, 3].init.init.last)
43
+ end
44
+
45
+ def test_cons
46
+ q1 = Deque.empty.cons(1)
47
+ assert_equal(1, q1.head)
48
+ assert(q1.tail.empty?)
49
+ q2 = q1.cons(2)
50
+ assert_equal(2, q2.head)
51
+ assert_equal(1, q2.tail.head)
52
+ assert(q2.tail.tail.empty?)
53
+ assert_equal(1, q1.head)
54
+ assert(q1.tail.empty?)
55
+
56
+ a = (1..1000).to_a.shuffle
57
+ q = a.inject(Deque.empty, :cons)
58
+ assert_equal(a.reverse, q.to_a)
59
+ end
60
+
61
+ def test_snoc
62
+ q1 = Deque.empty.snoc(1)
63
+ assert_equal(1, q1.head)
64
+ assert(q1.tail.empty?)
65
+ q2 = q1.snoc(2)
66
+ assert_equal(1, q2.head)
67
+ assert_equal(2, q2.tail.head)
68
+ assert(q2.tail.tail.empty?)
69
+ assert_equal(1, q1.head)
70
+ assert(q1.tail.empty?)
71
+
72
+ a = (1..1000).to_a.shuffle
73
+ q = a.inject(Deque.empty, :snoc)
74
+ assert_equal(a, q.to_a)
75
+ end
76
+
77
+ def test_invariants
78
+ a = (1..1000).to_a.shuffle
79
+ deque = a.inject(Deque.empty) { |d, i|
80
+ assert_deque_invariants(d)
81
+ if rand(2) == 0
82
+ d2 = d.snoc(i)
83
+ else
84
+ d2 = d.cons(i)
85
+ end
86
+ case rand(4)
87
+ when 0
88
+ d2.tail
89
+ when 1
90
+ d2.init
91
+ else
92
+ d2
93
+ end
94
+ }
95
+ assert_deque_invariants(deque)
96
+ until deque.empty?
97
+ if rand(2) == 0
98
+ deque = deque.tail
99
+ else
100
+ deque = deque.init
101
+ end
102
+ assert_deque_invariants(deque)
103
+ end
104
+ end
105
+
106
+ private
107
+
108
+ def assert_deque_invariants(d)
109
+ c = d.instance_variable_get(:@c)
110
+ front_len = d.instance_variable_get(:@front_len)
111
+ rear_len = d.instance_variable_get(:@rear_len)
112
+ assert(front_len <= c * rear_len + 1)
113
+ assert(rear_len <= c * front_len + 1)
114
+ end
115
+ end
116
+ end
@@ -1,7 +1,7 @@
1
1
  require_relative "../test_helper"
2
2
 
3
3
  with_tailcall_optimization {
4
- require "immutable/list"
4
+ require_relative "../../lib/immutable/list"
5
5
  }
6
6
 
7
7
  module Immutable
@@ -18,7 +18,7 @@ module Immutable
18
18
  end
19
19
 
20
20
  def test_head
21
- assert_raise(List::EmptyError) do
21
+ assert_raise(EmptyError) do
22
22
  List[].head
23
23
  end
24
24
  assert_equal(1, List[1].head)
@@ -26,7 +26,7 @@ module Immutable
26
26
  end
27
27
 
28
28
  def test_last
29
- assert_raise(List::EmptyError) do
29
+ assert_raise(EmptyError) do
30
30
  List[].last
31
31
  end
32
32
  assert_equal(1, List[1].last)
@@ -34,7 +34,7 @@ module Immutable
34
34
  end
35
35
 
36
36
  def test_tail
37
- assert_raise(List::EmptyError) do
37
+ assert_raise(EmptyError) do
38
38
  List[].tail
39
39
  end
40
40
  assert_equal(List[], List[1].tail)
@@ -42,7 +42,7 @@ module Immutable
42
42
  end
43
43
 
44
44
  def test_init
45
- assert_raise(List::EmptyError) do
45
+ assert_raise(EmptyError) do
46
46
  List[].init
47
47
  end
48
48
  assert_equal(List[], List[1].init)
@@ -56,13 +56,24 @@ module Immutable
56
56
  end
57
57
 
58
58
  def test_each
59
+ list = List[]
59
60
  a = []
60
- List[].each { |x| a << x }
61
+ assert_same(list, list.each { |x| a << x })
61
62
  assert_equal([], a)
62
-
63
+
64
+ list = List[1, 2, 3]
63
65
  a = []
64
- List[1, 2, 3].each { |x| a << x }
66
+ assert_same(list, list.each { |x| a << x })
65
67
  assert_equal([1, 2, 3], a)
68
+
69
+ enum = List[1, 2, 3].each
70
+ assert_instance_of(Enumerator, enum)
71
+ assert_equal(1, enum.next)
72
+ assert_equal(2, enum.next)
73
+ assert_equal(3, enum.next)
74
+ assert_raise(StopIteration) do
75
+ enum.next
76
+ end
66
77
  end
67
78
 
68
79
  def test_foldr
@@ -75,7 +86,7 @@ module Immutable
75
86
  end
76
87
 
77
88
  def test_foldr1
78
- assert_raise(List::EmptyError) do
89
+ assert_raise(EmptyError) do
79
90
  List[].foldr1(&:+)
80
91
  end
81
92
  assert_equal(1, List[1].foldr1(&:+))
@@ -94,7 +105,7 @@ module Immutable
94
105
  end
95
106
 
96
107
  def test_foldl1
97
- assert_raise(List::EmptyError) do
108
+ assert_raise(EmptyError) do
98
109
  List[].foldl1(&:+)
99
110
  end
100
111
  assert_equal(1, List[1].foldl1(&:+))
@@ -110,6 +121,7 @@ module Immutable
110
121
  assert(List[1] == List[1])
111
122
  assert(List[1] != List[2])
112
123
  assert(List[1] != [1])
124
+ assert(List[1] == List[1.0])
113
125
  assert(List["foo"] == List["foo"])
114
126
  assert(List["foo"] != List["bar"])
115
127
  assert(List[1, 2, 3] == List[1, 2, 3])
@@ -119,6 +131,20 @@ module Immutable
119
131
  assert(List[List[1, 2], List[3, 4]] != List[List[1, 2], List[3]])
120
132
  end
121
133
 
134
+ def test_eql
135
+ assert(List[].eql? List[])
136
+ assert(List[1].eql? List[1])
137
+ assert_same(List[1].eql?(List[1.0]), false)
138
+ assert(List["foo"].eql? List["foo"])
139
+ assert(List[1, 2, 3].eql? List[1, 2, 3])
140
+ assert(List[List[1, 2], List[3, 4]].eql? List[List[1, 2], List[3, 4]])
141
+ end
142
+
143
+ def test_hash_key
144
+ assert_same({List[1] => true}[List[1.0]], nil)
145
+ assert_same({List[1] => true}[List[1]], true)
146
+ end
147
+
122
148
  def test_inspect
123
149
  assert_equal('List[]', List[].inspect)
124
150
  assert_equal('List[1]', List[1].inspect)
@@ -135,6 +161,15 @@ module Immutable
135
161
  assert_equal(100, List[*(1..100)].length)
136
162
  end
137
163
 
164
+ def test_cons
165
+ assert_equal(List[1], List[].cons(1))
166
+ assert_equal(List[1, 2, 3], List[2, 3].cons(1))
167
+ xs = List[1, 2, 3]
168
+ ys = xs.cons(0)
169
+ assert_equal(List[1, 2, 3], xs)
170
+ assert_equal(List[0, 1, 2, 3], ys)
171
+ end
172
+
138
173
  def test_plus
139
174
  assert_equal(List[], List[] + List[])
140
175
  assert_equal(List[1, 2, 3], List[] + List[1, 2, 3])
@@ -156,6 +191,11 @@ module Immutable
156
191
  assert_equal(List["1", "2", "3"], List[1, 2, 3].map(&:to_s))
157
192
  end
158
193
 
194
+ def test_rev_map
195
+ assert_equal(List[], List[].rev_map(&:to_s))
196
+ assert_equal(List["3", "2", "1"], List[1, 2, 3].rev_map(&:to_s))
197
+ end
198
+
159
199
  def test_flat_map
160
200
  assert_equal(List[], List[].flat_map {})
161
201
  assert_equal(List["1", "2", "3"], List[1, 2, 3].map(&:to_s))
@@ -165,6 +205,14 @@ module Immutable
165
205
  assert_equal(nil, List[].find(&:odd?))
166
206
  assert_equal(1, List[1, 2, 3, 4, 5].find(&:odd?))
167
207
  assert_equal(2, List[1, 2, 3, 4, 5].find(&:even?))
208
+ assert_equal(nil, List[1, 2, 3, 4, 5].find{|elm|elm < 0})
209
+ assert_raise(ArgumentError) do
210
+ List[1, 2, 3, 4, 5].find(->{raise ArgumentError}){|elm|elm < 0}
211
+ end
212
+
213
+ enum = List[1, 2, 3, 4, 5].find
214
+ assert_instance_of(Enumerator, enum)
215
+ assert_equal(2, enum.each(&:even?))
168
216
  end
169
217
 
170
218
  def test_filter
@@ -268,9 +316,12 @@ module Immutable
268
316
  assert_equal(24, List[1, 2, 3, 4].product)
269
317
  end
270
318
 
271
- def test_s_unfoldr
319
+ def test_unfoldr
272
320
  xs = List.unfoldr(3) { |x| x == 0 ? nil : [x, x - 1] }
273
321
  assert_equal(List[3, 2, 1], xs)
322
+ end
323
+
324
+ def test_s_unfoldr
274
325
  xs = List.unfoldr("foo,bar,baz") { |x|
275
326
  if x.empty?
276
327
  nil
@@ -1,7 +1,8 @@
1
1
  require_relative "../test_helper"
2
2
 
3
3
  with_tailcall_optimization {
4
- require "immutable/map"
4
+ require_relative "../../lib/immutable/list"
5
+ require_relative "../../lib/immutable/map"
5
6
  }
6
7
 
7
8
  module Immutable
@@ -97,16 +98,6 @@ module Immutable
97
98
  assert_equal(List[[:a, 1], [:b, 2], [:c, 3]], xs)
98
99
  end
99
100
 
100
- def test_foldl_with_key
101
- xs = Map[].foldl_with_key(List[]) { |ys, k, v| Cons[[k, v], ys] }
102
- assert_equal(List[], xs)
103
-
104
- xs = Map[a: 1, c: 3, b: 2].foldl_with_key(List[]) { |ys, k, v|
105
- Cons[[k, v], ys]
106
- }
107
- assert_equal(List[[:c, 3], [:b, 2], [:a, 1]], xs)
108
- end
109
-
110
101
  def test_map
111
102
  xs = Map[].map { |v| v.to_s }
112
103
  assert_equal(List[], xs)
@@ -1,8 +1,8 @@
1
1
  require_relative "../test_helper"
2
2
 
3
3
  with_tailcall_optimization {
4
- require "immutable/promise"
5
- require "immutable/list"
4
+ require_relative "../../lib/immutable/promise"
5
+ require_relative "../../lib/immutable/list"
6
6
  }
7
7
 
8
8
  module Immutable
@@ -1,13 +1,13 @@
1
1
  require_relative "../test_helper"
2
2
 
3
3
  with_tailcall_optimization {
4
- require "immutable/queue"
4
+ require_relative "../../lib/immutable/queue"
5
5
  }
6
6
 
7
7
  module Immutable
8
- class TestList < Test::Unit::TestCase
8
+ class TestQueue < Test::Unit::TestCase
9
9
  def test_head
10
- assert_raise(List::EmptyError) do
10
+ assert_raise(EmptyError) do
11
11
  Queue[].head
12
12
  end
13
13
  assert_equal(1, Queue[1].head)
@@ -15,7 +15,7 @@ module Immutable
15
15
  end
16
16
 
17
17
  def test_tail
18
- assert_raise(List::EmptyError) do
18
+ assert_raise(EmptyError) do
19
19
  Queue[].tail
20
20
  end
21
21
  assert(Queue[1].tail.empty?)
@@ -39,5 +39,32 @@ module Immutable
39
39
  q = a.inject(Queue.empty, :snoc)
40
40
  assert_equal(a, q.to_a)
41
41
  end
42
+
43
+ def test_invariant
44
+ a = (1..100).to_a.shuffle
45
+ queue = a.inject(Queue.empty) { |q, i|
46
+ assert_queue_invariant(q)
47
+ q2 = q.snoc(i)
48
+ if rand(3) == 0
49
+ q2.tail
50
+ else
51
+ q2
52
+ end
53
+ }
54
+ assert_queue_invariant(queue)
55
+ until queue.empty?
56
+ queue = queue.tail
57
+ assert_queue_invariant(queue)
58
+ end
59
+ end
60
+
61
+ private
62
+
63
+ def assert_queue_invariant(d)
64
+ front = d.instance_variable_get(:@front)
65
+ rear = d.instance_variable_get(:@rear)
66
+ schedule = d.instance_variable_get(:@schedule)
67
+ assert_equal(schedule.length, front.length - rear.length)
68
+ end
42
69
  end
43
70
  end
@@ -1,7 +1,7 @@
1
1
  require_relative "../test_helper"
2
2
 
3
3
  with_tailcall_optimization {
4
- require "immutable/stream"
4
+ require_relative "../../lib/immutable/stream"
5
5
  }
6
6
 
7
7
  module Immutable
@@ -33,38 +33,40 @@ module Immutable
33
33
  assert_equal(Stream[1, 3, 5], Stream.from(1, 2).take(3))
34
34
  end
35
35
 
36
- def test_prepend
37
- assert_equal(Stream[1], Stream.null.prepend { 1 })
38
- assert_equal(Stream[1, 2], Stream.null.prepend { 2 }.prepend { 1 })
36
+ def test_cons
37
+ assert_equal(Stream[1], Stream.empty.cons(1))
38
+ assert_equal(Stream[1, 2], Stream.empty.cons(2).cons(1))
39
+ assert_equal(Stream[1], Stream.empty.cons { 1 })
40
+ assert_equal(Stream[1, 2], Stream.empty.cons { 2 }.cons { 1 })
39
41
  end
40
42
 
41
43
  def test_head
42
- assert_raise(List::EmptyError) do
43
- Stream.null.head
44
+ assert_raise(EmptyError) do
45
+ Stream.empty.head
44
46
  end
45
47
  assert_equal(1, Stream[1].head)
46
48
  assert_equal(1, Stream[1, 2, 3].head)
47
49
  end
48
50
 
49
51
  def test_tail
50
- assert_raise(List::EmptyError) do
51
- Stream.null.tail
52
+ assert_raise(EmptyError) do
53
+ Stream.empty.tail
52
54
  end
53
- assert(Stream[1].tail.null?)
55
+ assert(Stream[1].tail.empty?)
54
56
  assert_equal([2, 3], Stream[1, 2, 3].tail.to_a)
55
57
  end
56
58
 
57
59
  def test_last
58
- assert_raise(List::EmptyError) do
59
- Stream.null.last
60
+ assert_raise(EmptyError) do
61
+ Stream.empty.last
60
62
  end
61
63
  assert_equal(1, Stream[1].last)
62
64
  assert_equal(3, Stream[1, 2, 3].last)
63
65
  end
64
66
 
65
67
  def test_init
66
- assert_raise(List::EmptyError) do
67
- Stream.null.init.force
68
+ assert_raise(EmptyError) do
69
+ Stream.empty.init.force
68
70
  end
69
71
  assert_equal(Stream[], Stream[1].init)
70
72
  assert_equal(Stream[1], Stream[1, 2].init)
@@ -108,7 +110,7 @@ module Immutable
108
110
  end
109
111
 
110
112
  def test_foldr1
111
- assert_raise(List::EmptyError) do
113
+ assert_raise(EmptyError) do
112
114
  Stream[].foldr1(&:+)
113
115
  end
114
116
  assert_equal(1, Stream[1].foldr1(&:+))
@@ -127,7 +129,7 @@ module Immutable
127
129
  end
128
130
 
129
131
  def test_foldl1
130
- assert_raise(List::EmptyError) do
132
+ assert_raise(EmptyError) do
131
133
  Stream[].foldl1(&:+)
132
134
  end
133
135
  assert_equal(1, Stream[1].foldl1(&:+))
@@ -307,9 +309,12 @@ module Immutable
307
309
  assert_equal(Stream[], Stream[1, 2, 3].drop_while { |x| x < 4 })
308
310
  end
309
311
 
310
- def test_s_unfoldr
312
+ def test_unfoldr
311
313
  xs = Stream.unfoldr(3) { |x| x == 0 ? nil : [x, x - 1] }
312
314
  assert_equal(Stream[3, 2, 1], xs)
315
+ end
316
+
317
+ def test_s_unfoldr
313
318
  xs = Stream.unfoldr("foo,bar,baz") { |x|
314
319
  if x.empty?
315
320
  nil
@@ -355,5 +360,10 @@ module Immutable
355
360
  }
356
361
  assert_equal(Stream[0, 6, 12, 18], s)
357
362
  end
363
+
364
+ def test_to_list
365
+ assert_equal(List[], Stream[].to_list)
366
+ assert_equal(List[1, 2, 3], Stream.from(1).take(3).to_list)
367
+ end
358
368
  end
359
369
  end