immutable 0.3.1 → 0.3.2
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 +7 -0
- data/README.md +8 -4
- data/lib/immutable.rb +10 -6
- data/lib/immutable/consable.rb +8 -2
- data/lib/immutable/foldable.rb +2 -2
- data/lib/immutable/headable.rb +130 -5
- data/lib/immutable/map.rb +3 -0
- data/lib/immutable/stream.rb +2 -0
- data/test/immutable/test_list.rb +156 -2
- data/test/immutable/test_map.rb +5 -0
- data/test/immutable/test_stream.rb +37 -0
- data/test/test_helper.rb +12 -8
- metadata +46 -56
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: b88830d271351b2eb0b7580fc69e71beb7233165
|
4
|
+
data.tar.gz: ea7083277f60f1c54ae3bb41d9661f7d78186050
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c407518f109f1fc47c2ee3ce6370e762a2207516007117f15877d8038d2ef8fdcb3c9dff0afd53f89271ba640a6ed738c064ccce62b30d75fa073041bef379b1
|
7
|
+
data.tar.gz: c082da1cddcbdb9a72161f9f7750df331f7794953feca638b7ed928ba3617d20a8eec5dba837dc6d6efaa0074ee5ced23c6d8e3937c392c283189e6e18d18376
|
data/README.md
CHANGED
@@ -3,18 +3,22 @@ immutable - immutable data structures for Ruby
|
|
3
3
|
|
4
4
|
This project aims to provide immutable data structures for Ruby.
|
5
5
|
|
6
|
+
[](http://travis-ci.org/shugo/immutable)
|
7
|
+
|
6
8
|
Install
|
7
|
-
|
9
|
+
-------
|
8
10
|
|
9
|
-
|
11
|
+
```bash
|
12
|
+
$ gem install immutable
|
13
|
+
```
|
10
14
|
|
11
15
|
Documentation
|
12
|
-
|
16
|
+
-------------
|
13
17
|
|
14
18
|
* [API Reference](http://rubydoc.info/github/shugo/immutable/frames)
|
15
19
|
|
16
20
|
License
|
17
|
-
|
21
|
+
-------
|
18
22
|
|
19
23
|
(The MIT License)
|
20
24
|
|
data/lib/immutable.rb
CHANGED
@@ -2,11 +2,13 @@
|
|
2
2
|
module Immutable
|
3
3
|
end
|
4
4
|
|
5
|
-
|
6
|
-
RubyVM::InstructionSequence.compile_option
|
7
|
-
|
8
|
-
|
9
|
-
|
5
|
+
if defined?(RubyVM)
|
6
|
+
old_compile_option = RubyVM::InstructionSequence.compile_option
|
7
|
+
RubyVM::InstructionSequence.compile_option = {
|
8
|
+
:tailcall_optimization => true,
|
9
|
+
:trace_instruction => false
|
10
|
+
}
|
11
|
+
end
|
10
12
|
begin
|
11
13
|
require_relative "immutable/list"
|
12
14
|
require_relative "immutable/map"
|
@@ -16,5 +18,7 @@ begin
|
|
16
18
|
require_relative "immutable/output_restricted_deque"
|
17
19
|
require_relative "immutable/deque"
|
18
20
|
ensure
|
19
|
-
RubyVM
|
21
|
+
if defined?(RubyVM)
|
22
|
+
RubyVM::InstructionSequence.compile_option = old_compile_option
|
23
|
+
end
|
20
24
|
end
|
data/lib/immutable/consable.rb
CHANGED
@@ -180,7 +180,7 @@ module Immutable
|
|
180
180
|
#
|
181
181
|
# @return [Consable] the concatenated +Consable+ object.
|
182
182
|
def flatten
|
183
|
-
foldr(empty) { |x, xs| x
|
183
|
+
foldr(empty) { |x, xs| safe_append(x, xs) }
|
184
184
|
end
|
185
185
|
|
186
186
|
alias concat flatten
|
@@ -190,7 +190,7 @@ module Immutable
|
|
190
190
|
#
|
191
191
|
# @return [Consable] the obtained +Consable+ object.
|
192
192
|
def flat_map
|
193
|
-
foldr(empty) { |x, xs| yield(x)
|
193
|
+
foldr(empty) { |x, xs| safe_append(yield(x), xs) }
|
194
194
|
end
|
195
195
|
|
196
196
|
alias concat_map flat_map
|
@@ -340,5 +340,11 @@ module Immutable
|
|
340
340
|
def Cons(x, y)
|
341
341
|
y.cons(x)
|
342
342
|
end
|
343
|
+
|
344
|
+
def safe_append(xs, ys)
|
345
|
+
xs.foldr(ys) { |z, zs| Cons(z, zs) }
|
346
|
+
rescue NoMethodError
|
347
|
+
Cons(xs, ys)
|
348
|
+
end
|
343
349
|
end
|
344
350
|
end
|
data/lib/immutable/foldable.rb
CHANGED
@@ -26,14 +26,14 @@ module Immutable
|
|
26
26
|
#
|
27
27
|
# @return [#+] the sum of the numbers.
|
28
28
|
def sum
|
29
|
-
foldl(0,
|
29
|
+
foldl(0) { |x, y| x + y }
|
30
30
|
end
|
31
31
|
|
32
32
|
# Computes the product of the numbers in +self+.
|
33
33
|
#
|
34
34
|
# @return [#*] the product of the numbers.
|
35
35
|
def product
|
36
|
-
foldl(1,
|
36
|
+
foldl(1) { |x, y| x * y }
|
37
37
|
end
|
38
38
|
end
|
39
39
|
end
|
data/lib/immutable/headable.rb
CHANGED
@@ -70,6 +70,8 @@ module Immutable
|
|
70
70
|
end
|
71
71
|
end
|
72
72
|
|
73
|
+
alias to_s inspect
|
74
|
+
|
73
75
|
# Returns whether +self+ equals to +x+.
|
74
76
|
#
|
75
77
|
# @param [Object] x the object to compare.
|
@@ -119,10 +121,21 @@ module Immutable
|
|
119
121
|
self
|
120
122
|
end
|
121
123
|
|
124
|
+
# Calls +block+ once for each index in +self+.
|
125
|
+
# @yield [index]
|
126
|
+
# @yieldparam [Integer] index
|
127
|
+
# @yieldreturn [self]
|
128
|
+
# @return [Enumerator]
|
129
|
+
def each_index
|
130
|
+
return to_enum(__callee__) unless block_given?
|
131
|
+
|
132
|
+
each_with_index{ |_, idx| yield(idx) }
|
133
|
+
end
|
134
|
+
|
122
135
|
# Reduces +self+ using +block+ from right to left. +e+ is used as the
|
123
136
|
# starting value. For example:
|
124
137
|
#
|
125
|
-
# List[1, 2, 3].foldr(9) { |x, y| x
|
138
|
+
# List[1, 2, 3].foldr(9) { |x, y| x - y } #=> 1 - (2 - (3 - 9)) = -7
|
126
139
|
#
|
127
140
|
# @param [Object] e the start value.
|
128
141
|
# @return [Object] the reduced value.
|
@@ -153,7 +166,7 @@ module Immutable
|
|
153
166
|
# Reduces +self+ using +block+ from left to right. +e+ is used as the
|
154
167
|
# starting value. For example:
|
155
168
|
#
|
156
|
-
# List[1, 2, 3].foldl(9) { |x, y| x
|
169
|
+
# List[1, 2, 3].foldl(9) { |x, y| x - y } #=> ((9 - 1) - 2) - 3 = 3
|
157
170
|
#
|
158
171
|
# @param [Object] e the start value.
|
159
172
|
# @return [Object] the reduced value.
|
@@ -208,15 +221,127 @@ module Immutable
|
|
208
221
|
# Returns the +n+th element of +self+. If +n+ is out of range, +nil+ is
|
209
222
|
# returned.
|
210
223
|
#
|
224
|
+
# @param [Integer, #to_int] n
|
211
225
|
# @return [Object] the +n+th element.
|
212
226
|
def [](n)
|
213
|
-
|
227
|
+
raise TypeError unless n.respond_to?(:to_int)
|
228
|
+
int = n.to_int
|
229
|
+
|
230
|
+
if int < 0 || empty?
|
214
231
|
nil
|
215
|
-
elsif
|
232
|
+
elsif int == 0
|
216
233
|
head
|
217
234
|
else
|
218
|
-
tail[
|
235
|
+
tail[int - 1]
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
alias at []
|
240
|
+
|
241
|
+
# Returns the +n+th element of +self+. If +n+ is out of range, +IndexError+
|
242
|
+
# returned.
|
243
|
+
#
|
244
|
+
# @overload fetch(n)
|
245
|
+
# @param [Integer, #to_int] n
|
246
|
+
# @return [Object] the +n+th element.
|
247
|
+
# @raise [IndexError] if n is out of rage
|
248
|
+
# @overload fetch(n, ifnone)
|
249
|
+
# @param [Integer, #to_int] n
|
250
|
+
# @return ifnone
|
251
|
+
# @overload fetch(n) {|n|}
|
252
|
+
# @param [Integer, #to_int] n
|
253
|
+
# @yield [n]
|
254
|
+
# @yieldparam [Integer, #to_int] n
|
255
|
+
def fetch(*args)
|
256
|
+
alen = args.length
|
257
|
+
n, ifnone = *args
|
258
|
+
|
259
|
+
unless (1..2).cover?(alen)
|
260
|
+
raise ArgumentError, "wrong number of arguments (#{alen} for 1..2)"
|
219
261
|
end
|
262
|
+
|
263
|
+
raise TypeError unless n.respond_to?(:to_int)
|
264
|
+
int = n.to_int
|
265
|
+
|
266
|
+
return at(int) if int >= 0 && int < length
|
267
|
+
|
268
|
+
if block_given?
|
269
|
+
if alen == 2
|
270
|
+
warn "#{__LINE__}:warning: block supersedes default value argument"
|
271
|
+
end
|
272
|
+
|
273
|
+
yield n
|
274
|
+
else
|
275
|
+
if alen == 2
|
276
|
+
ifnone
|
277
|
+
else
|
278
|
+
raise IndexError, "index #{int} outside of list bounds"
|
279
|
+
end
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
# @overload index(val)
|
284
|
+
# @return [Integer, nil] index
|
285
|
+
# @overload index
|
286
|
+
# @return [Enumerator]
|
287
|
+
# @overload index {}
|
288
|
+
# @yieldreturn [Integer, nil] index
|
289
|
+
def index(*args)
|
290
|
+
alen = args.length
|
291
|
+
val = args.first
|
292
|
+
|
293
|
+
raise ArgumentError unless (0..1).cover?(alen)
|
294
|
+
return to_enum(__callee__) if !block_given? && alen == 0
|
295
|
+
|
296
|
+
if alen == 1
|
297
|
+
if block_given?
|
298
|
+
warn "#{__LINE__}:warning: given block not used"
|
299
|
+
end
|
300
|
+
|
301
|
+
each_with_index { |e, idx|
|
302
|
+
return idx if e == val
|
303
|
+
}
|
304
|
+
else
|
305
|
+
if block_given?
|
306
|
+
each_with_index { |e, idx|
|
307
|
+
return idx if yield(e)
|
308
|
+
}
|
309
|
+
end
|
310
|
+
end
|
311
|
+
|
312
|
+
nil
|
313
|
+
end
|
314
|
+
|
315
|
+
# @overload rindex(val)
|
316
|
+
# @return [Integer, nil] index
|
317
|
+
# @overload rindex
|
318
|
+
# @return [Enumerator]
|
319
|
+
# @overload rindex {}
|
320
|
+
# @yieldreturn [Integer, nil] index
|
321
|
+
def rindex(*args)
|
322
|
+
alen = args.length
|
323
|
+
val = args.first
|
324
|
+
|
325
|
+
raise ArgumentError unless (0..1).cover?(alen)
|
326
|
+
return to_enum(__callee__) if !block_given? && alen == 0
|
327
|
+
|
328
|
+
if alen == 1
|
329
|
+
if block_given?
|
330
|
+
warn "#{__LINE__}:warning: given block not used"
|
331
|
+
end
|
332
|
+
|
333
|
+
reverse_each.with_index { |e, idx|
|
334
|
+
return length - (idx + 1) if e == val
|
335
|
+
}
|
336
|
+
else
|
337
|
+
if block_given?
|
338
|
+
reverse_each.with_index { |e, idx|
|
339
|
+
return length - (idx + 1) if yield(e)
|
340
|
+
}
|
341
|
+
end
|
342
|
+
end
|
343
|
+
|
344
|
+
nil
|
220
345
|
end
|
221
346
|
|
222
347
|
# Converts +self+ to a list.
|
data/lib/immutable/map.rb
CHANGED
@@ -66,6 +66,7 @@ module Immutable
|
|
66
66
|
end
|
67
67
|
end
|
68
68
|
|
69
|
+
# @return [String]
|
69
70
|
def inspect
|
70
71
|
"Map[" + foldr_with_key("") { |k, v, s|
|
71
72
|
x = k.inspect + " => " + v.inspect
|
@@ -77,6 +78,8 @@ module Immutable
|
|
77
78
|
} + "]"
|
78
79
|
end
|
79
80
|
|
81
|
+
alias to_s inspect
|
82
|
+
|
80
83
|
# Calls +block+ once for each key/value in +self+.
|
81
84
|
def each(&block)
|
82
85
|
foldl_with_key(nil) { |x, k, v| yield([k, v]) }
|
data/lib/immutable/stream.rb
CHANGED
data/test/immutable/test_list.rb
CHANGED
@@ -14,7 +14,7 @@ module Immutable
|
|
14
14
|
def test_s_from_enum
|
15
15
|
assert_equal(List[], List.from_enum([]))
|
16
16
|
assert_equal(List[1, 2, 3], List.from_enum(1..3))
|
17
|
-
assert_equal(List["a", "b", "c"], List.from_enum("abc".
|
17
|
+
assert_equal(List["a", "b", "c"], List.from_enum("abc".each_char))
|
18
18
|
end
|
19
19
|
|
20
20
|
def test_head
|
@@ -76,6 +76,84 @@ module Immutable
|
|
76
76
|
end
|
77
77
|
end
|
78
78
|
|
79
|
+
def test_each_index
|
80
|
+
list = List[]
|
81
|
+
a = []
|
82
|
+
assert_same(list, list.each_index { |x| a << x })
|
83
|
+
assert_equal([], a)
|
84
|
+
|
85
|
+
list = List[1, 2, 3]
|
86
|
+
a = []
|
87
|
+
assert_same(list, list.each_index { |x| a << x })
|
88
|
+
assert_equal([0, 1, 2], a)
|
89
|
+
|
90
|
+
enum = List[1, 2, 3].each_index
|
91
|
+
assert_instance_of(Enumerator, enum)
|
92
|
+
assert_equal(0, enum.next)
|
93
|
+
assert_equal(1, enum.next)
|
94
|
+
assert_equal(2, enum.next)
|
95
|
+
assert_raise(StopIteration) do
|
96
|
+
enum.next
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def test_index
|
101
|
+
list = List[]
|
102
|
+
assert_equal(nil, list.index(1))
|
103
|
+
|
104
|
+
list = List[1, 2, 1]
|
105
|
+
assert_equal(0, list.index(1))
|
106
|
+
assert_equal(1, list.index(2))
|
107
|
+
assert_equal(nil, list.index(3))
|
108
|
+
|
109
|
+
verbose = $VERBOSE
|
110
|
+
$VERBOSE = nil
|
111
|
+
list = List[1, 2, 1]
|
112
|
+
assert_equal(0, list.index(1) {|e| e * 2 == 4 })
|
113
|
+
assert_equal(1, list.index(2) {|e| e * 2 == 4 })
|
114
|
+
assert_equal(nil, list.index(3) {|e| e * 2 == 4 })
|
115
|
+
$VERBOSE = verbose
|
116
|
+
|
117
|
+
list = List[1, 2, 1]
|
118
|
+
assert_equal(0, list.index {|e| e * 2 == 2 })
|
119
|
+
assert_equal(1, list.index {|e| e * 2 == 4 })
|
120
|
+
assert_equal(nil, list.index {|e| e * 2 == 6 })
|
121
|
+
|
122
|
+
enum = List[1, 2, 1].index
|
123
|
+
assert_instance_of(Enumerator, enum)
|
124
|
+
assert_equal(0, enum.each {|v|v == 1})
|
125
|
+
assert_equal(1, enum.each {|v|v == 2})
|
126
|
+
assert_equal(nil, enum.each {|v|v == 3})
|
127
|
+
end
|
128
|
+
|
129
|
+
def test_rindex
|
130
|
+
list = List[]
|
131
|
+
assert_equal(nil, list.rindex(1))
|
132
|
+
|
133
|
+
list = List[1, 2, 1]
|
134
|
+
assert_equal(2, list.rindex(1))
|
135
|
+
assert_equal(1, list.rindex(2))
|
136
|
+
assert_equal(nil, list.rindex(3))
|
137
|
+
|
138
|
+
verbose = $VERBOSE
|
139
|
+
$VERBOSE = nil
|
140
|
+
list = List[1, 2, 1]
|
141
|
+
assert_equal(2, list.rindex(1) {|e| e * 2 == 4 })
|
142
|
+
assert_equal(1, list.rindex(2) {|e| e * 2 == 4 })
|
143
|
+
assert_equal(nil, list.rindex(3) {|e| e * 2 == 4 })
|
144
|
+
$VERBOSE = verbose
|
145
|
+
|
146
|
+
list = List[1, 2, 1]
|
147
|
+
assert_equal(2, list.rindex {|e| e * 2 == 2 })
|
148
|
+
assert_equal(1, list.rindex {|e| e * 2 == 4 })
|
149
|
+
assert_equal(nil, list.rindex {|e| e * 2 == 6 })
|
150
|
+
|
151
|
+
enum = List[1, 2, 1].rindex
|
152
|
+
assert_instance_of(Enumerator, enum)
|
153
|
+
assert_equal(2, enum.each {|v|v == 1})
|
154
|
+
assert_equal(nil, enum.each {|v|v == 3})
|
155
|
+
end
|
156
|
+
|
79
157
|
def test_foldr
|
80
158
|
assert_equal(0, List[].foldr(0, &:+))
|
81
159
|
assert_equal(123, List[].foldr(123, &:+))
|
@@ -154,6 +232,15 @@ module Immutable
|
|
154
232
|
List[List[1, 2], List[3, 4]].inspect)
|
155
233
|
end
|
156
234
|
|
235
|
+
def test_to_s
|
236
|
+
assert_equal('List[]', List[].to_s)
|
237
|
+
assert_equal('List[1]', List[1].to_s)
|
238
|
+
assert_equal('List["foo"]', List["foo"].to_s)
|
239
|
+
assert_equal('List[1, 2, 3]', List[1, 2, 3].to_s)
|
240
|
+
assert_equal('List[List[1, 2], List[3, 4]]',
|
241
|
+
List[List[1, 2], List[3, 4]].to_s)
|
242
|
+
end
|
243
|
+
|
157
244
|
def test_length
|
158
245
|
assert_equal(0, List[].length)
|
159
246
|
assert_equal(1, List[1].length)
|
@@ -184,6 +271,10 @@ module Immutable
|
|
184
271
|
assert_equal(List[List[1]], List[List[List[1]]].flatten)
|
185
272
|
assert_equal(List[1, 2, 3], List[List[1, 2], List[3]].flatten)
|
186
273
|
assert_equal(List[1, 2, 3], List[List[1], List[2], List[3]].flatten)
|
274
|
+
assert_equal(List[1, 2, 3], List[List[1], 2, List[3]].flatten)
|
275
|
+
assert_equal(List[1, [2], 3], List[List[1], [2], List[3]].flatten)
|
276
|
+
obj = Object.new
|
277
|
+
assert_equal(List[obj, 'str', obj], List[obj, 'str', obj].flatten)
|
187
278
|
end
|
188
279
|
|
189
280
|
def test_map
|
@@ -198,7 +289,9 @@ module Immutable
|
|
198
289
|
|
199
290
|
def test_flat_map
|
200
291
|
assert_equal(List[], List[].flat_map {})
|
201
|
-
|
292
|
+
xs = List["foo", "bar"].flat_map {|s| List.from_enum(s.each_char)}
|
293
|
+
assert_equal(List["f", "o", "o", "b", "a", "r"], xs)
|
294
|
+
xs = List["FOO", "BAR"].flat_map {|s| s.upcase}
|
202
295
|
end
|
203
296
|
|
204
297
|
def test_find
|
@@ -228,6 +321,67 @@ module Immutable
|
|
228
321
|
assert_equal(2, List[1, 2, 3][1])
|
229
322
|
assert_equal(3, List[1, 2, 3][2])
|
230
323
|
assert_equal(nil, List[1, 2, 3][3])
|
324
|
+
assert_equal(2, List[1, 2, 3][1.1])
|
325
|
+
assert_raise TypeError do
|
326
|
+
List[1, 2, 3]['1']
|
327
|
+
end
|
328
|
+
end
|
329
|
+
|
330
|
+
def test_at
|
331
|
+
assert_equal(nil, List[].at(0))
|
332
|
+
assert_equal(1, List[1, 2, 3].at(0))
|
333
|
+
assert_equal(nil, List[1, 2, 3].at(-1))
|
334
|
+
assert_equal(2, List[1, 2, 3].at(1))
|
335
|
+
assert_equal(3, List[1, 2, 3].at(2))
|
336
|
+
assert_equal(nil, List[1, 2, 3].at(3))
|
337
|
+
assert_equal(2, List[1, 2, 3].at(1.1))
|
338
|
+
assert_raise TypeError do
|
339
|
+
List[1, 2, 3].at('1')
|
340
|
+
end
|
341
|
+
end
|
342
|
+
|
343
|
+
def test_fetch
|
344
|
+
assert_raise ArgumentError do
|
345
|
+
List[].fetch
|
346
|
+
end
|
347
|
+
|
348
|
+
assert_raise IndexError do
|
349
|
+
List[].fetch(0)
|
350
|
+
end
|
351
|
+
|
352
|
+
assert_equal(1, List[1, 2, 3].fetch(0))
|
353
|
+
|
354
|
+
assert_raise IndexError do
|
355
|
+
List[1, 2, 3].fetch(-1)
|
356
|
+
end
|
357
|
+
|
358
|
+
assert_equal(2, List[1, 2, 3].fetch(1))
|
359
|
+
assert_equal(3, List[1, 2, 3].fetch(2))
|
360
|
+
|
361
|
+
assert_raise IndexError do
|
362
|
+
List[1, 2, 3].fetch(3)
|
363
|
+
end
|
364
|
+
|
365
|
+
assert_equal(2, List[1, 2, 3].fetch(1.1))
|
366
|
+
|
367
|
+
assert_raise TypeError do
|
368
|
+
List[1, 2, 3].fetch('1')
|
369
|
+
end
|
370
|
+
|
371
|
+
assert_equal(9, List[].fetch(0, 9))
|
372
|
+
assert_equal(2, List[1, 2, 3].fetch(1, 9))
|
373
|
+
assert_equal(9, List[1, 2, 3].fetch(4, 9))
|
374
|
+
|
375
|
+
assert_equal(5, List[].fetch(0) {|n| n + 5 })
|
376
|
+
assert_equal(2, List[1, 2, 3].fetch(1) {|n| n + 5 })
|
377
|
+
assert_equal(8, List[1, 2, 3].fetch(4) {|n| n * 2 })
|
378
|
+
|
379
|
+
verbose = $VERBOSE
|
380
|
+
$VERBOSE = nil
|
381
|
+
assert_equal(5, List[].fetch(0, 9) {|n| n + 5 })
|
382
|
+
assert_equal(2, List[1, 2, 3].fetch(1, 9) {|n| n + 5 })
|
383
|
+
assert_equal(8, List[1, 2, 3].fetch(4, 9) {|n| n * 2 })
|
384
|
+
$VERBOSE = verbose
|
231
385
|
end
|
232
386
|
|
233
387
|
def test_take
|
data/test/immutable/test_map.rb
CHANGED
@@ -18,6 +18,11 @@ module Immutable
|
|
18
18
|
assert_equal("Map[:a => 1, :b => 2]", Map[a: 1, b: 2].inspect)
|
19
19
|
end
|
20
20
|
|
21
|
+
def test_to_s
|
22
|
+
assert_equal("Map[]", Map.empty.to_s)
|
23
|
+
assert_equal("Map[:a => 1, :b => 2]", Map[a: 1, b: 2].to_s)
|
24
|
+
end
|
25
|
+
|
21
26
|
def test_insert
|
22
27
|
5.times do
|
23
28
|
map = (1..100).to_a.shuffle.inject(Map.empty) { |m, k|
|
@@ -196,6 +196,43 @@ module Immutable
|
|
196
196
|
s.inspect)
|
197
197
|
end
|
198
198
|
|
199
|
+
def test_to_s
|
200
|
+
s = Stream[]
|
201
|
+
assert_equal('Stream[...]', s.to_s)
|
202
|
+
assert_equal(nil, s[0])
|
203
|
+
assert_equal('Stream[]', s.to_s)
|
204
|
+
s = Stream[1]
|
205
|
+
assert_equal('Stream[...]', s.to_s)
|
206
|
+
assert_equal(1, s[0])
|
207
|
+
assert_equal('Stream[1, ...]', s.to_s)
|
208
|
+
assert_equal(nil, s[1])
|
209
|
+
assert_equal('Stream[1]', s.to_s)
|
210
|
+
s = Stream["foo"]
|
211
|
+
assert_equal("foo", s[0])
|
212
|
+
assert_equal('Stream["foo", ...]', s.to_s)
|
213
|
+
assert_equal(nil, s[1])
|
214
|
+
assert_equal('Stream["foo"]', s.to_s)
|
215
|
+
s = Stream[1, 2, 3]
|
216
|
+
assert_equal('Stream[...]', s.to_s)
|
217
|
+
assert_equal(1, s[0])
|
218
|
+
assert_equal('Stream[1, ...]', s.to_s)
|
219
|
+
assert_equal(2, s[1])
|
220
|
+
assert_equal('Stream[1, 2, ...]', s.to_s)
|
221
|
+
assert_equal(3, s[2])
|
222
|
+
assert_equal('Stream[1, 2, 3, ...]', s.to_s)
|
223
|
+
assert_equal(nil, s[3])
|
224
|
+
assert_equal('Stream[1, 2, 3]', s.to_s)
|
225
|
+
s = Stream[1, 2, 3]
|
226
|
+
assert_equal(2, s[1])
|
227
|
+
assert_equal('Stream[?, 2, ...]', s.to_s)
|
228
|
+
s = Stream[Stream[1, 2], Stream[3, 4]]
|
229
|
+
assert_equal(Stream[1, 2], s[0])
|
230
|
+
assert_equal(Stream[3, 4], s[1])
|
231
|
+
assert_equal(nil, s[2])
|
232
|
+
assert_equal('Stream[Stream[1, 2], Stream[3, 4]]',
|
233
|
+
s.to_s)
|
234
|
+
end
|
235
|
+
|
199
236
|
def test_length
|
200
237
|
assert_equal(0, Stream[].length)
|
201
238
|
assert_equal(1, Stream[1].length)
|
data/test/test_helper.rb
CHANGED
@@ -3,14 +3,18 @@ $VERBOSE = true
|
|
3
3
|
require "test/unit"
|
4
4
|
|
5
5
|
def with_tailcall_optimization
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
6
|
+
if defined?(RubyVM)
|
7
|
+
old_compile_option = RubyVM::InstructionSequence.compile_option
|
8
|
+
RubyVM::InstructionSequence.compile_option = {
|
9
|
+
:tailcall_optimization => true,
|
10
|
+
:trace_instruction => false
|
11
|
+
}
|
12
|
+
begin
|
13
|
+
yield
|
14
|
+
ensure
|
15
|
+
RubyVM::InstructionSequence.compile_option = old_compile_option
|
16
|
+
end
|
17
|
+
else
|
12
18
|
yield
|
13
|
-
ensure
|
14
|
-
RubyVM::InstructionSequence.compile_option = old_compile_option
|
15
19
|
end
|
16
20
|
end
|
metadata
CHANGED
@@ -1,76 +1,66 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: immutable
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
version: 0.3.1
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.3.2
|
6
5
|
platform: ruby
|
7
|
-
authors:
|
8
|
-
|
6
|
+
authors:
|
7
|
+
- Shugo Maeda
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
|
13
|
-
date: 2012-09-07 00:00:00 Z
|
11
|
+
date: 2016-07-08 00:00:00.000000000 Z
|
14
12
|
dependencies: []
|
15
|
-
|
16
13
|
description:
|
17
14
|
email: shugo@ruby-lang.org
|
18
15
|
executables: []
|
19
|
-
|
20
16
|
extensions: []
|
21
|
-
|
22
17
|
extra_rdoc_files: []
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
- README.md
|
18
|
+
files:
|
19
|
+
- README.md
|
20
|
+
- benchmark/benchmark_deque.rb
|
21
|
+
- benchmark/benchmark_map.rb
|
22
|
+
- benchmark/benchmark_parallel_fib.rb
|
23
|
+
- benchmark/benchmark_queue.rb
|
24
|
+
- lib/immutable.rb
|
25
|
+
- lib/immutable/consable.rb
|
26
|
+
- lib/immutable/deque.rb
|
27
|
+
- lib/immutable/foldable.rb
|
28
|
+
- lib/immutable/headable.rb
|
29
|
+
- lib/immutable/list.rb
|
30
|
+
- lib/immutable/map.rb
|
31
|
+
- lib/immutable/output_restricted_deque.rb
|
32
|
+
- lib/immutable/promise.rb
|
33
|
+
- lib/immutable/queue.rb
|
34
|
+
- lib/immutable/stream.rb
|
35
|
+
- test/immutable/test_deque.rb
|
36
|
+
- test/immutable/test_list.rb
|
37
|
+
- test/immutable/test_map.rb
|
38
|
+
- test/immutable/test_promise.rb
|
39
|
+
- test/immutable/test_queue.rb
|
40
|
+
- test/immutable/test_stream.rb
|
41
|
+
- test/test_helper.rb
|
48
42
|
homepage: http://github.com/shugo/immutable
|
49
43
|
licenses: []
|
50
|
-
|
44
|
+
metadata: {}
|
51
45
|
post_install_message:
|
52
46
|
rdoc_options: []
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
- - ">="
|
66
|
-
- !ruby/object:Gem::Version
|
67
|
-
version: "0"
|
47
|
+
require_paths:
|
48
|
+
- lib
|
49
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
55
|
+
requirements:
|
56
|
+
- - ">="
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
version: '0'
|
68
59
|
requirements: []
|
69
|
-
|
70
60
|
rubyforge_project:
|
71
|
-
rubygems_version:
|
61
|
+
rubygems_version: 2.5.1
|
72
62
|
signing_key:
|
73
|
-
specification_version:
|
63
|
+
specification_version: 4
|
74
64
|
summary: Immutable data structures for Ruby
|
75
65
|
test_files: []
|
76
|
-
|
66
|
+
has_rdoc:
|