immutable 0.2.0 → 0.3.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.
@@ -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