immutable-ruby 0.1.0 → 0.2.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.
@@ -1,1554 +1,3 @@
1
- require 'immutable/enumerable'
2
- require 'immutable/hash'
3
-
4
- module Immutable
5
- # A `Vector` is an ordered, integer-indexed collection of objects. Like
6
- # Ruby's `Array`, `Vector` indexing starts at zero and negative indexes count
7
- # back from the end.
8
- #
9
- # `Vector` has a similar interface to `Array`. The main difference is methods
10
- # that would destructively update an `Array` (such as {#insert} or
11
- # {#delete_at}) instead return new `Vectors` and leave the existing one
12
- # unchanged.
13
- #
14
- # ### Creating New Vectors
15
- #
16
- # Immutable::Vector.new([:first, :second, :third])
17
- # Immutable::Vector[1, 2, 3, 4, 5]
18
- #
19
- # ### Retrieving Items from Vectors
20
- #
21
- # vector = Immutable::Vector[1, 2, 3, 4, 5]
22
- #
23
- # vector[0] # => 1
24
- # vector[-1] # => 5
25
- # vector[0,3] # => Immutable::Vector[1, 2, 3]
26
- # vector[1..-1] # => Immutable::Vector[2, 3, 4, 5]
27
- # vector.first # => 1
28
- # vector.last # => 5
29
- #
30
- # ### Creating Modified Vectors
31
- #
32
- # vector.add(6) # => Immutable::Vector[1, 2, 3, 4, 5, 6]
33
- # vector.insert(1, :a, :b) # => Immutable::Vector[1, :a, :b, 2, 3, 4, 5]
34
- # vector.delete_at(2) # => Immutable::Vector[1, 2, 4, 5]
35
- # vector + [6, 7] # => Immutable::Vector[1, 2, 3, 4, 5, 6, 7]
36
- #
37
- class Vector
38
- include Immutable::Enumerable
39
-
40
- # @private
41
- BLOCK_SIZE = 32
42
- # @private
43
- INDEX_MASK = BLOCK_SIZE - 1
44
- # @private
45
- BITS_PER_LEVEL = 5
46
-
47
- # Return the number of items in this `Vector`
48
- # @return [Integer]
49
- attr_reader :size
50
- alias length size
51
-
52
- class << self
53
- # Create a new `Vector` populated with the given items.
54
- # @return [Vector]
55
- def [](*items)
56
- new(items.freeze)
57
- end
58
-
59
- # Return an empty `Vector`. If used on a subclass, returns an empty instance
60
- # of that class.
61
- #
62
- # @return [Vector]
63
- def empty
64
- @empty ||= new
65
- end
66
-
67
- # "Raw" allocation of a new `Vector`. Used internally to create a new
68
- # instance quickly after building a modified trie.
69
- #
70
- # @return [Vector]
71
- # @private
72
- def alloc(root, size, levels)
73
- obj = allocate
74
- obj.instance_variable_set(:@root, root)
75
- obj.instance_variable_set(:@size, size)
76
- obj.instance_variable_set(:@levels, levels)
77
- obj.freeze
78
- end
79
- end
80
-
81
- def initialize(items=[].freeze)
82
- items = items.to_a
83
- if items.size <= 32
84
- items = items.dup.freeze if !items.frozen?
85
- @root, @size, @levels = items, items.size, 0
86
- else
87
- root, size, levels = items, items.size, 0
88
- while root.size > 32
89
- root = root.each_slice(32).to_a
90
- levels += 1
91
- end
92
- @root, @size, @levels = root.freeze, size, levels
93
- end
94
- freeze
95
- end
96
-
97
- # Return `true` if this `Vector` contains no items.
98
- #
99
- # @return [Boolean]
100
- def empty?
101
- @size == 0
102
- end
103
-
104
- # Return the first item in the `Vector`. If the vector is empty, return `nil`.
105
- #
106
- # @example
107
- # Immutable::Vector["A", "B", "C"].first # => "A"
108
- #
109
- # @return [Object]
110
- def first
111
- get(0)
112
- end
113
-
114
- # Return the last item in the `Vector`. If the vector is empty, return `nil`.
115
- #
116
- # @example
117
- # Immutable::Vector["A", "B", "C"].last # => "C"
118
- #
119
- # @return [Object]
120
- def last
121
- get(-1)
122
- end
123
-
124
- # Return a new `Vector` with `item` added after the last occupied position.
125
- #
126
- # @example
127
- # Immutable::Vector[1, 2].add(99) # => Immutable::Vector[1, 2, 99]
128
- #
129
- # @param item [Object] The object to insert at the end of the vector
130
- # @return [Vector]
131
- def add(item)
132
- update_root(@size, item)
133
- end
134
- alias << add
135
- alias push add
136
-
137
- # Return a new `Vector` with a new value at the given `index`. If `index`
138
- # is greater than the length of the vector, the returned vector will be
139
- # padded with `nil`s to the correct size.
140
- #
141
- # @overload set(index, item)
142
- # Return a new `Vector` with the item at `index` replaced by `item`.
143
- #
144
- # @param item [Object] The object to insert into that position
145
- # @example
146
- # Immutable::Vector[1, 2, 3, 4].set(2, 99)
147
- # # => Immutable::Vector[1, 2, 99, 4]
148
- # Immutable::Vector[1, 2, 3, 4].set(-1, 99)
149
- # # => Immutable::Vector[1, 2, 3, 99]
150
- # Immutable::Vector[].set(2, 99)
151
- # # => Immutable::Vector[nil, nil, 99]
152
- #
153
- # @overload set(index)
154
- # Return a new `Vector` with the item at `index` replaced by the return
155
- # value of the block.
156
- #
157
- # @yield (existing) Once with the existing value at the given `index`.
158
- # @example
159
- # Immutable::Vector[1, 2, 3, 4].set(2) { |v| v * 10 }
160
- # # => Immutable::Vector[1, 2, 30, 4]
161
- #
162
- # @param index [Integer] The index to update. May be negative.
163
- # @return [Vector]
164
- def set(index, item = yield(get(index)))
165
- raise IndexError, "index #{index} outside of vector bounds" if index < -@size
166
- index += @size if index < 0
167
- if index > @size
168
- suffix = Array.new(index - @size, nil)
169
- suffix << item
170
- replace_suffix(@size, suffix)
171
- else
172
- update_root(index, item)
173
- end
174
- end
175
-
176
- # Return a new `Vector` with a deeply nested value modified to the result
177
- # of the given code block. When traversing the nested `Vector`s and
178
- # `Hash`es, non-existing keys are created with empty `Hash` values.
179
- #
180
- # The code block receives the existing value of the deeply nested key (or
181
- # `nil` if it doesn't exist). This is useful for "transforming" the value
182
- # associated with a certain key.
183
- #
184
- # Note that the original `Vector` and sub-`Vector`s and sub-`Hash`es are
185
- # left unmodified; new data structure copies are created along the path
186
- # wherever needed.
187
- #
188
- # @example
189
- # v = Immutable::Vector[123, 456, 789, Immutable::Hash["a" => Immutable::Vector[5, 6, 7]]]
190
- # v.update_in(3, "a", 1) { |value| value + 9 }
191
- # # => Immutable::Vector[123, 456, 789, Immutable::Hash["a" => Immutable::Vector[5, 15, 7]]]
192
- #
193
- # @param key_path [Object(s)] List of keys which form the path to the key to be modified
194
- # @yield [value] The previously stored value
195
- # @yieldreturn [Object] The new value to store
196
- # @return [Vector]
197
- def update_in(*key_path, &block)
198
- if key_path.empty?
199
- raise ArgumentError, 'must have at least one key in path'
200
- end
201
- key = key_path[0]
202
- if key_path.size == 1
203
- new_value = block.call(get(key))
204
- else
205
- value = fetch(key, Immutable::EmptyHash)
206
- new_value = value.update_in(*key_path[1..-1], &block)
207
- end
208
- set(key, new_value)
209
- end
210
-
211
- # Retrieve the item at `index`. If there is none (either the provided index
212
- # is too high or too low), return `nil`.
213
- #
214
- # @example
215
- # v = Immutable::Vector["A", "B", "C", "D"]
216
- # v.get(2) # => "C"
217
- # v.get(-1) # => "D"
218
- # v.get(4) # => nil
219
- #
220
- # @param index [Integer] The index to retrieve
221
- # @return [Object]
222
- def get(index)
223
- return nil if @size == 0
224
- index += @size if index < 0
225
- return nil if index >= @size || index < 0
226
- leaf_node_for(@root, @levels * BITS_PER_LEVEL, index)[index & INDEX_MASK]
227
- end
228
- alias at get
229
-
230
- # Retrieve the value at `index` with optional default.
231
- #
232
- # @overload fetch(index)
233
- # Retrieve the value at the given index, or raise an `IndexError` if not
234
- # found.
235
- #
236
- # @param index [Integer] The index to look up
237
- # @raise [IndexError] if index does not exist
238
- # @example
239
- # v = Immutable::Vector["A", "B", "C", "D"]
240
- # v.fetch(2) # => "C"
241
- # v.fetch(-1) # => "D"
242
- # v.fetch(4) # => IndexError: index 4 outside of vector bounds
243
- #
244
- # @overload fetch(index) { |index| ... }
245
- # Retrieve the value at the given index, or return the result of yielding
246
- # the block if not found.
247
- #
248
- # @yield Once if the index is not found.
249
- # @yieldparam [Integer] index The index which does not exist
250
- # @yieldreturn [Object] Default value to return
251
- # @param index [Integer] The index to look up
252
- # @example
253
- # v = Immutable::Vector["A", "B", "C", "D"]
254
- # v.fetch(2) { |i| i * i } # => "C"
255
- # v.fetch(4) { |i| i * i } # => 16
256
- #
257
- # @overload fetch(index, default)
258
- # Retrieve the value at the given index, or return the provided `default`
259
- # value if not found.
260
- #
261
- # @param index [Integer] The index to look up
262
- # @param default [Object] Object to return if the key is not found
263
- # @example
264
- # v = Immutable::Vector["A", "B", "C", "D"]
265
- # v.fetch(2, "Z") # => "C"
266
- # v.fetch(4, "Z") # => "Z"
267
- #
268
- # @return [Object]
269
- def fetch(index, default = (missing_default = true))
270
- if index >= -@size && index < @size
271
- get(index)
272
- elsif block_given?
273
- yield(index)
274
- elsif !missing_default
275
- default
276
- else
277
- raise IndexError, "index #{index} outside of vector bounds"
278
- end
279
- end
280
-
281
- # Return the value of successively indexing into a nested collection.
282
- # If any of the keys is not present, return `nil`.
283
- #
284
- # @example
285
- # v = Immutable::Vector[9, Immutable::Hash[c: 'a', d: 4]]
286
- # v.dig(1, :c) # => "a"
287
- # v.dig(1, :f) # => nil
288
- #
289
- # @return [Object]
290
- def dig(key, *rest)
291
- value = self[key]
292
- if rest.empty? || value.nil?
293
- value
294
- else
295
- value.dig(*rest)
296
- end
297
- end
298
-
299
- # Return specific objects from the `Vector`. All overloads return `nil` if
300
- # the starting index is out of range.
301
- #
302
- # @overload vector.slice(index)
303
- # Returns a single object at the given `index`. If `index` is negative,
304
- # count backwards from the end.
305
- #
306
- # @param index [Integer] The index to retrieve. May be negative.
307
- # @return [Object]
308
- # @example
309
- # v = Immutable::Vector["A", "B", "C", "D", "E", "F"]
310
- # v[2] # => "C"
311
- # v[-1] # => "F"
312
- # v[6] # => nil
313
- #
314
- # @overload vector.slice(index, length)
315
- # Return a subvector starting at `index` and continuing for `length`
316
- # elements or until the end of the `Vector`, whichever occurs first.
317
- #
318
- # @param start [Integer] The index to start retrieving items from. May be
319
- # negative.
320
- # @param length [Integer] The number of items to retrieve.
321
- # @return [Vector]
322
- # @example
323
- # v = Immutable::Vector["A", "B", "C", "D", "E", "F"]
324
- # v[2, 3] # => Immutable::Vector["C", "D", "E"]
325
- # v[-2, 3] # => Immutable::Vector["E", "F"]
326
- # v[20, 1] # => nil
327
- #
328
- # @overload vector.slice(index..end)
329
- # Return a subvector starting at `index` and continuing to index
330
- # `end` or the end of the `Vector`, whichever occurs first.
331
- #
332
- # @param range [Range] The range of indices to retrieve.
333
- # @return [Vector]
334
- # @example
335
- # v = Immutable::Vector["A", "B", "C", "D", "E", "F"]
336
- # v[2..3] # => Immutable::Vector["C", "D"]
337
- # v[-2..100] # => Immutable::Vector["E", "F"]
338
- # v[20..21] # => nil
339
- def slice(arg, length = (missing_length = true))
340
- if missing_length
341
- if arg.is_a?(Range)
342
- from, to = arg.begin, arg.end
343
- from += @size if from < 0
344
- to += @size if to < 0
345
- to += 1 if !arg.exclude_end?
346
- length = to - from
347
- length = 0 if length < 0
348
- subsequence(from, length)
349
- else
350
- get(arg)
351
- end
352
- else
353
- arg += @size if arg < 0
354
- subsequence(arg, length)
355
- end
356
- end
357
- alias [] slice
358
-
359
- # Return a new `Vector` with the given values inserted before the element
360
- # at `index`. If `index` is greater than the current length, `nil` values
361
- # are added to pad the `Vector` to the required size.
362
- #
363
- # @example
364
- # Immutable::Vector["A", "B", "C", "D"].insert(2, "X", "Y", "Z")
365
- # # => Immutable::Vector["A", "B", "X", "Y", "Z", "C", "D"]
366
- # Immutable::Vector[].insert(2, "X", "Y", "Z")
367
- # # => Immutable::Vector[nil, nil, "X", "Y", "Z"]
368
- #
369
- # @param index [Integer] The index where the new items should go
370
- # @param items [Array] The items to add
371
- # @return [Vector]
372
- # @raise [IndexError] if index exceeds negative range.
373
- def insert(index, *items)
374
- raise IndexError if index < -@size
375
- index += @size if index < 0
376
-
377
- if index < @size
378
- suffix = flatten_suffix(@root, @levels * BITS_PER_LEVEL, index, [])
379
- suffix.unshift(*items)
380
- elsif index == @size
381
- suffix = items
382
- else
383
- suffix = Array.new(index - @size, nil).concat(items)
384
- index = @size
385
- end
386
-
387
- replace_suffix(index, suffix)
388
- end
389
-
390
- # Return a new `Vector` with the element at `index` removed. If the given `index`
391
- # does not exist, return `self`.
392
- #
393
- # @example
394
- # Immutable::Vector["A", "B", "C", "D"].delete_at(2)
395
- # # => Immutable::Vector["A", "B", "D"]
396
- #
397
- # @param index [Integer] The index to remove
398
- # @return [Vector]
399
- def delete_at(index)
400
- return self if index >= @size || index < -@size
401
- index += @size if index < 0
402
-
403
- suffix = flatten_suffix(@root, @levels * BITS_PER_LEVEL, index, [])
404
- replace_suffix(index, suffix.tap(&:shift))
405
- end
406
-
407
- # Return a new `Vector` with the last element removed. Return `self` if
408
- # empty.
409
- #
410
- # @example
411
- # Immutable::Vector["A", "B", "C"].pop # => Immutable::Vector["A", "B"]
412
- #
413
- # @return [Vector]
414
- def pop
415
- return self if @size == 0
416
- replace_suffix(@size-1, [])
417
- end
418
-
419
- # Return a new `Vector` with `object` inserted before the first element,
420
- # moving the other elements upwards.
421
- #
422
- # @example
423
- # Immutable::Vector["A", "B"].unshift("Z")
424
- # # => Immutable::Vector["Z", "A", "B"]
425
- #
426
- # @param object [Object] The value to prepend
427
- # @return [Vector]
428
- def unshift(object)
429
- insert(0, object)
430
- end
431
-
432
- # Return a new `Vector` with the first element removed. If empty, return
433
- # `self`.
434
- #
435
- # @example
436
- # Immutable::Vector["A", "B", "C"].shift # => Immutable::Vector["B", "C"]
437
- #
438
- # @return [Vector]
439
- def shift
440
- delete_at(0)
441
- end
442
-
443
- # Call the given block once for each item in the vector, passing each
444
- # item from first to last successively to the block. If no block is given,
445
- # an `Enumerator` is returned instead.
446
- #
447
- # @example
448
- # Immutable::Vector["A", "B", "C"].each { |e| puts "Element: #{e}" }
449
- #
450
- # Element: A
451
- # Element: B
452
- # Element: C
453
- # # => Immutable::Vector["A", "B", "C"]
454
- #
455
- # @return [self, Enumerator]
456
- def each(&block)
457
- return to_enum unless block_given?
458
- traverse_depth_first(@root, @levels, &block)
459
- self
460
- end
461
-
462
- # Call the given block once for each item in the vector, from last to
463
- # first.
464
- #
465
- # @example
466
- # Immutable::Vector["A", "B", "C"].reverse_each { |e| puts "Element: #{e}" }
467
- #
468
- # Element: C
469
- # Element: B
470
- # Element: A
471
- #
472
- # @return [self]
473
- def reverse_each(&block)
474
- return enum_for(:reverse_each) unless block_given?
475
- reverse_traverse_depth_first(@root, @levels, &block)
476
- self
477
- end
478
-
479
- # Return a new `Vector` containing all elements for which the given block returns
480
- # true.
481
- #
482
- # @example
483
- # Immutable::Vector["Bird", "Cow", "Elephant"].select { |e| e.size >= 4 }
484
- # # => Immutable::Vector["Bird", "Elephant"]
485
- #
486
- # @return [Vector]
487
- # @yield [element] Once for each element.
488
- def select
489
- return enum_for(:select) unless block_given?
490
- reduce(self.class.empty) { |vector, item| yield(item) ? vector.add(item) : vector }
491
- end
492
- alias find_all select
493
- alias keep_if select
494
-
495
- # Return a new `Vector` with all items which are equal to `obj` removed.
496
- # `#==` is used for checking equality.
497
- #
498
- # @example
499
- # Immutable::Vector["C", "B", "A", "B"].delete("B") # => Immutable::Vector["C", "A"]
500
- #
501
- # @param obj [Object] The object to remove (every occurrence)
502
- # @return [Vector]
503
- def delete(obj)
504
- select { |item| item != obj }
505
- end
506
-
507
- # Invoke the given block once for each item in the vector, and return a new
508
- # `Vector` containing the values returned by the block. If no block is
509
- # provided, return an enumerator.
510
- #
511
- # @example
512
- # Immutable::Vector[3, 2, 1].map { |e| e * e } # => Immutable::Vector[9, 4, 1]
513
- #
514
- # @return [Vector, Enumerator]
515
- def map
516
- return enum_for(:map) if not block_given?
517
- return self if empty?
518
- self.class.new(super)
519
- end
520
- alias collect map
521
-
522
- # Return a new `Vector` with the concatenated results of running the block once
523
- # for every element in this `Vector`.
524
- #
525
- # @example
526
- # Immutable::Vector[1, 2, 3].flat_map { |x| [x, -x] }
527
- # # => Immutable::Vector[1, -1, 2, -2, 3, -3]
528
- #
529
- # @return [Vector]
530
- def flat_map
531
- return enum_for(:flat_map) if not block_given?
532
- return self if empty?
533
- self.class.new(super)
534
- end
535
-
536
- # Return a new `Vector` with the same elements as this one, but randomly permuted.
537
- #
538
- # @example
539
- # Immutable::Vector[1, 2, 3, 4].shuffle # => Immutable::Vector[4, 1, 3, 2]
540
- #
541
- # @return [Vector]
542
- def shuffle
543
- self.class.new(((array = to_a).frozen? ? array.shuffle : array.shuffle!).freeze)
544
- end
545
-
546
- # Return a new `Vector` with no duplicate elements, as determined by `#hash` and
547
- # `#eql?`. For each group of equivalent elements, only the first will be retained.
548
- #
549
- # @example
550
- # Immutable::Vector["A", "B", "C", "B"].uniq # => Immutable::Vector["A", "B", "C"]
551
- # Immutable::Vector["a", "A", "b"].uniq(&:upcase) # => Immutable::Vector["a", "b"]
552
- #
553
- # @return [Vector]
554
- def uniq(&block)
555
- array = to_a
556
- if array.frozen?
557
- self.class.new(array.uniq(&block).freeze)
558
- elsif array.uniq!(&block) # returns nil if no changes were made
559
- self.class.new(array.freeze)
560
- else
561
- self
562
- end
563
- end
564
-
565
- # Return a new `Vector` with the same elements as this one, but in reverse order.
566
- #
567
- # @example
568
- # Immutable::Vector["A", "B", "C"].reverse # => Immutable::Vector["C", "B", "A"]
569
- #
570
- # @return [Vector]
571
- def reverse
572
- self.class.new(((array = to_a).frozen? ? array.reverse : array.reverse!).freeze)
573
- end
574
-
575
- # Return a new `Vector` with the same elements, but rotated so that the one at
576
- # index `count` is the first element of the new vector. If `count` is positive,
577
- # the elements will be shifted left, and those shifted past the lowest position
578
- # will be moved to the end. If `count` is negative, the elements will be shifted
579
- # right, and those shifted past the last position will be moved to the beginning.
580
- #
581
- # @example
582
- # v = Immutable::Vector["A", "B", "C", "D", "E", "F"]
583
- # v.rotate(2) # => Immutable::Vector["C", "D", "E", "F", "A", "B"]
584
- # v.rotate(-1) # => Immutable::Vector["F", "A", "B", "C", "D", "E"]
585
- #
586
- # @param count [Integer] The number of positions to shift items by
587
- # @return [Vector]
588
- def rotate(count = 1)
589
- return self if (count % @size) == 0
590
- self.class.new(((array = to_a).frozen? ? array.rotate(count) : array.rotate!(count)).freeze)
591
- end
592
-
593
- # Return a new `Vector` with all nested vectors and arrays recursively "flattened
594
- # out". That is, their elements inserted into the new `Vector` in the place where
595
- # the nested array/vector originally was. If an optional `level` argument is
596
- # provided, the flattening will only be done recursively that number of times.
597
- # A `level` of 0 means not to flatten at all, 1 means to only flatten nested
598
- # arrays/vectors which are directly contained within this `Vector`.
599
- #
600
- # @example
601
- # v = Immutable::Vector["A", Immutable::Vector["B", "C", Immutable::Vector["D"]]]
602
- # v.flatten(1)
603
- # # => Immutable::Vector["A", "B", "C", Immutable::Vector["D"]]
604
- # v.flatten
605
- # # => Immutable::Vector["A", "B", "C", "D"]
606
- #
607
- # @param level [Integer] The depth to which flattening should be applied
608
- # @return [Vector]
609
- def flatten(level = -1)
610
- return self if level == 0
611
- array = to_a
612
- if array.frozen?
613
- self.class.new(array.flatten(level).freeze)
614
- elsif array.flatten!(level) # returns nil if no changes were made
615
- self.class.new(array.freeze)
616
- else
617
- self
618
- end
619
- end
620
-
621
- # Return a new `Vector` built by concatenating this one with `other`. `other`
622
- # can be any object which is convertible to an `Array` using `#to_a`.
623
- #
624
- # @example
625
- # Immutable::Vector["A", "B", "C"] + ["D", "E"]
626
- # # => Immutable::Vector["A", "B", "C", "D", "E"]
627
- #
628
- # @param other [Enumerable] The collection to concatenate onto this vector
629
- # @return [Vector]
630
- def +(other)
631
- other = other.to_a
632
- other = other.dup if other.frozen?
633
- replace_suffix(@size, other)
634
- end
635
- alias concat +
636
-
637
- # Combine two vectors by "zipping" them together. `others` should be arrays
638
- # and/or vectors. The corresponding elements from this `Vector` and each of
639
- # `others` (that is, the elements with the same indices) will be gathered
640
- # into arrays.
641
- #
642
- # If `others` contains fewer elements than this vector, `nil` will be used
643
- # for padding.
644
- #
645
- # @overload zip(*others)
646
- # Return a new vector containing the new arrays.
647
- #
648
- # @return [Vector]
649
- #
650
- # @overload zip(*others)
651
- # @yield [pair] once for each array
652
- # @return [nil]
653
- #
654
- # @example
655
- # v1 = Immutable::Vector["A", "B", "C"]
656
- # v2 = Immutable::Vector[1, 2]
657
- # v1.zip(v2)
658
- # # => Immutable::Vector[["A", 1], ["B", 2], ["C", nil]]
659
- #
660
- # @param others [Array] The arrays/vectors to zip together with this one
661
- # @return [Vector]
662
- def zip(*others)
663
- if block_given?
664
- super
665
- else
666
- self.class.new(super)
667
- end
668
- end
669
-
670
- # Return a new `Vector` with the same items, but sorted.
671
- #
672
- # @overload sort
673
- # Compare elements with their natural sort key (`#<=>`).
674
- #
675
- # @example
676
- # Immutable::Vector["Elephant", "Dog", "Lion"].sort
677
- # # => Immutable::Vector["Dog", "Elephant", "Lion"]
678
- #
679
- # @overload sort
680
- # Uses the block as a comparator to determine sorted order.
681
- #
682
- # @yield [a, b] Any number of times with different pairs of elements.
683
- # @yieldreturn [Integer] Negative if the first element should be sorted
684
- # lower, positive if the latter element, or 0 if
685
- # equal.
686
- # @example
687
- # Immutable::Vector["Elephant", "Dog", "Lion"].sort { |a,b| a.size <=> b.size }
688
- # # => Immutable::Vector["Dog", "Lion", "Elephant"]
689
- #
690
- # @return [Vector]
691
- def sort
692
- self.class.new(super)
693
- end
694
-
695
- # Return a new `Vector` with the same items, but sorted. The sort order is
696
- # determined by mapping the items through the given block to obtain sort
697
- # keys, and then sorting the keys according to their natural sort order
698
- # (`#<=>`).
699
- #
700
- # @yield [element] Once for each element.
701
- # @yieldreturn a sort key object for the yielded element.
702
- # @example
703
- # Immutable::Vector["Elephant", "Dog", "Lion"].sort_by { |e| e.size }
704
- # # => Immutable::Vector["Dog", "Lion", "Elephant"]
705
- #
706
- # @return [Vector]
707
- def sort_by
708
- self.class.new(super)
709
- end
710
-
711
- # Drop the first `n` elements and return the rest in a new `Vector`.
712
- #
713
- # @example
714
- # Immutable::Vector["A", "B", "C", "D", "E", "F"].drop(2)
715
- # # => Immutable::Vector["C", "D", "E", "F"]
716
- #
717
- # @param n [Integer] The number of elements to remove
718
- # @return [Vector]
719
- # @raise ArgumentError if `n` is negative.
720
- def drop(n)
721
- return self if n == 0
722
- return self.class.empty if n >= @size
723
- raise ArgumentError, 'attempt to drop negative size' if n < 0
724
- self.class.new(flatten_suffix(@root, @levels * BITS_PER_LEVEL, n, []))
725
- end
726
-
727
- # Return only the first `n` elements in a new `Vector`.
728
- #
729
- # @example
730
- # Immutable::Vector["A", "B", "C", "D", "E", "F"].take(4)
731
- # # => Immutable::Vector["A", "B", "C", "D"]
732
- #
733
- # @param n [Integer] The number of elements to retain
734
- # @return [Vector]
735
- def take(n)
736
- return self if n >= @size
737
- self.class.new(super)
738
- end
739
-
740
- # Drop elements up to, but not including, the first element for which the
741
- # block returns `nil` or `false`. Gather the remaining elements into a new
742
- # `Vector`. If no block is given, an `Enumerator` is returned instead.
743
- #
744
- # @example
745
- # Immutable::Vector[1, 3, 5, 7, 6, 4, 2].drop_while { |e| e < 5 }
746
- # # => Immutable::Vector[5, 7, 6, 4, 2]
747
- #
748
- # @return [Vector, Enumerator]
749
- def drop_while
750
- return enum_for(:drop_while) if not block_given?
751
- self.class.new(super)
752
- end
753
-
754
- # Gather elements up to, but not including, the first element for which the
755
- # block returns `nil` or `false`, and return them in a new `Vector`. If no block
756
- # is given, an `Enumerator` is returned instead.
757
- #
758
- # @example
759
- # Immutable::Vector[1, 3, 5, 7, 6, 4, 2].take_while { |e| e < 5 }
760
- # # => Immutable::Vector[1, 3]
761
- #
762
- # @return [Vector, Enumerator]
763
- def take_while
764
- return enum_for(:take_while) if not block_given?
765
- self.class.new(super)
766
- end
767
-
768
- # Repetition. Return a new `Vector` built by concatenating `times` copies
769
- # of this one together.
770
- #
771
- # @example
772
- # Immutable::Vector["A", "B"] * 3
773
- # # => Immutable::Vector["A", "B", "A", "B", "A", "B"]
774
- #
775
- # @param times [Integer] The number of times to repeat the elements in this vector
776
- # @return [Vector]
777
- def *(times)
778
- return self.class.empty if times == 0
779
- return self if times == 1
780
- result = (to_a * times)
781
- result.is_a?(Array) ? self.class.new(result) : result
782
- end
783
-
784
- # Replace a range of indexes with the given object.
785
- #
786
- # @overload fill(object)
787
- # Return a new `Vector` of the same size, with every index set to
788
- # `object`.
789
- #
790
- # @param [Object] object Fill value.
791
- # @example
792
- # Immutable::Vector["A", "B", "C", "D", "E", "F"].fill("Z")
793
- # # => Immutable::Vector["Z", "Z", "Z", "Z", "Z", "Z"]
794
- #
795
- # @overload fill(object, index)
796
- # Return a new `Vector` with all indexes from `index` to the end of the
797
- # vector set to `object`.
798
- #
799
- # @param [Object] object Fill value.
800
- # @param [Integer] index Starting index. May be negative.
801
- # @example
802
- # Immutable::Vector["A", "B", "C", "D", "E", "F"].fill("Z", 3)
803
- # # => Immutable::Vector["A", "B", "C", "Z", "Z", "Z"]
804
- #
805
- # @overload fill(object, index, length)
806
- # Return a new `Vector` with `length` indexes, beginning from `index`,
807
- # set to `object`. Expands the `Vector` if `length` would extend beyond
808
- # the current length.
809
- #
810
- # @param [Object] object Fill value.
811
- # @param [Integer] index Starting index. May be negative.
812
- # @param [Integer] length
813
- # @example
814
- # Immutable::Vector["A", "B", "C", "D", "E", "F"].fill("Z", 3, 2)
815
- # # => Immutable::Vector["A", "B", "C", "Z", "Z", "F"]
816
- # Immutable::Vector["A", "B"].fill("Z", 1, 5)
817
- # # => Immutable::Vector["A", "Z", "Z", "Z", "Z", "Z"]
818
- #
819
- # @return [Vector]
820
- # @raise [IndexError] if index is out of negative range.
821
- def fill(object, index = 0, length = nil)
822
- raise IndexError if index < -@size
823
- index += @size if index < 0
824
- length ||= @size - index # to the end of the array, if no length given
825
-
826
- if index < @size
827
- suffix = flatten_suffix(@root, @levels * BITS_PER_LEVEL, index, [])
828
- suffix.fill(object, 0, length)
829
- elsif index == @size
830
- suffix = Array.new(length, object)
831
- else
832
- suffix = Array.new(index - @size, nil).concat(Array.new(length, object))
833
- index = @size
834
- end
835
-
836
- replace_suffix(index, suffix)
837
- end
838
-
839
- # When invoked with a block, yields all combinations of length `n` of items
840
- # from the `Vector`, and then returns `self`. There is no guarantee about
841
- # which order the combinations will be yielded.
842
- #
843
- # If no block is given, an `Enumerator` is returned instead.
844
- #
845
- # @example
846
- # v = Immutable::Vector[5, 6, 7, 8]
847
- # v.combination(3) { |c| puts "Combination: #{c}" }
848
- #
849
- # Combination: [5, 6, 7]
850
- # Combination: [5, 6, 8]
851
- # Combination: [5, 7, 8]
852
- # Combination: [6, 7, 8]
853
- # #=> Immutable::Vector[5, 6, 7, 8]
854
- #
855
- # @return [self, Enumerator]
856
- def combination(n)
857
- return enum_for(:combination, n) if not block_given?
858
- return self if n < 0 || @size < n
859
- if n == 0
860
- yield []
861
- elsif n == 1
862
- each { |item| yield [item] }
863
- elsif n == @size
864
- yield to_a
865
- else
866
- combos = lambda do |result,index,remaining|
867
- while @size - index > remaining
868
- if remaining == 1
869
- yield result.dup << get(index)
870
- else
871
- combos[result.dup << get(index), index+1, remaining-1]
872
- end
873
- index += 1
874
- end
875
- index.upto(@size-1) { |i| result << get(i) }
876
- yield result
877
- end
878
- combos[[], 0, n]
879
- end
880
- self
881
- end
882
-
883
- # When invoked with a block, yields all repeated combinations of length `n` of
884
- # items from the `Vector`, and then returns `self`. A "repeated combination" is
885
- # one in which any item from the `Vector` can appear consecutively any number of
886
- # times.
887
- #
888
- # There is no guarantee about which order the combinations will be yielded in.
889
- #
890
- # If no block is given, an `Enumerator` is returned instead.
891
- #
892
- # @example
893
- # v = Immutable::Vector[5, 6, 7, 8]
894
- # v.repeated_combination(2) { |c| puts "Combination: #{c}" }
895
- #
896
- # Combination: [5, 5]
897
- # Combination: [5, 6]
898
- # Combination: [5, 7]
899
- # Combination: [5, 8]
900
- # Combination: [6, 6]
901
- # Combination: [6, 7]
902
- # Combination: [6, 8]
903
- # Combination: [7, 7]
904
- # Combination: [7, 8]
905
- # Combination: [8, 8]
906
- # # => Immutable::Vector[5, 6, 7, 8]
907
- #
908
- # @return [self, Enumerator]
909
- def repeated_combination(n)
910
- return enum_for(:repeated_combination, n) if not block_given?
911
- if n < 0
912
- # yield nothing
913
- elsif n == 0
914
- yield []
915
- elsif n == 1
916
- each { |item| yield [item] }
917
- elsif @size == 0
918
- # yield nothing
919
- else
920
- combos = lambda do |result,index,remaining|
921
- while index < @size-1
922
- if remaining == 1
923
- yield result.dup << get(index)
924
- else
925
- combos[result.dup << get(index), index, remaining-1]
926
- end
927
- index += 1
928
- end
929
- item = get(index)
930
- remaining.times { result << item }
931
- yield result
932
- end
933
- combos[[], 0, n]
934
- end
935
- self
936
- end
937
-
938
- # Yields all permutations of length `n` of items from the `Vector`, and then
939
- # returns `self`. If no length `n` is specified, permutations of all elements
940
- # will be yielded.
941
- #
942
- # There is no guarantee about which order the permutations will be yielded in.
943
- #
944
- # If no block is given, an `Enumerator` is returned instead.
945
- #
946
- # @example
947
- # v = Immutable::Vector[5, 6, 7]
948
- # v.permutation(2) { |p| puts "Permutation: #{p}" }
949
- #
950
- # Permutation: [5, 6]
951
- # Permutation: [5, 7]
952
- # Permutation: [6, 5]
953
- # Permutation: [6, 7]
954
- # Permutation: [7, 5]
955
- # Permutation: [7, 6]
956
- # # => Immutable::Vector[5, 6, 7]
957
- #
958
- # @return [self, Enumerator]
959
- def permutation(n = @size)
960
- return enum_for(:permutation, n) if not block_given?
961
- if n < 0 || @size < n
962
- # yield nothing
963
- elsif n == 0
964
- yield []
965
- elsif n == 1
966
- each { |item| yield [item] }
967
- else
968
- used, result = [], []
969
- perms = lambda do |index|
970
- 0.upto(@size-1) do |i|
971
- next if used[i]
972
- result[index] = get(i)
973
- if index < n-1
974
- used[i] = true
975
- perms[index+1]
976
- used[i] = false
977
- else
978
- yield result.dup
979
- end
980
- end
981
- end
982
- perms[0]
983
- end
984
- self
985
- end
986
-
987
- # When invoked with a block, yields all repeated permutations of length `n` of
988
- # items from the `Vector`, and then returns `self`. A "repeated permutation" is
989
- # one where any item from the `Vector` can appear any number of times, and in
990
- # any position (not just consecutively)
991
- #
992
- # If no length `n` is specified, permutations of all elements will be yielded.
993
- # There is no guarantee about which order the permutations will be yielded in.
994
- #
995
- # If no block is given, an `Enumerator` is returned instead.
996
- #
997
- # @example
998
- # v = Immutable::Vector[5, 6, 7]
999
- # v.repeated_permutation(2) { |p| puts "Permutation: #{p}" }
1000
- #
1001
- # Permutation: [5, 5]
1002
- # Permutation: [5, 6]
1003
- # Permutation: [5, 7]
1004
- # Permutation: [6, 5]
1005
- # Permutation: [6, 6]
1006
- # Permutation: [6, 7]
1007
- # Permutation: [7, 5]
1008
- # Permutation: [7, 6]
1009
- # Permutation: [7, 7]
1010
- # # => Immutable::Vector[5, 6, 7]
1011
- #
1012
- # @return [self, Enumerator]
1013
- def repeated_permutation(n = @size)
1014
- return enum_for(:repeated_permutation, n) if not block_given?
1015
- if n < 0
1016
- # yield nothing
1017
- elsif n == 0
1018
- yield []
1019
- elsif n == 1
1020
- each { |item| yield [item] }
1021
- else
1022
- result = []
1023
- perms = lambda do |index|
1024
- 0.upto(@size-1) do |i|
1025
- result[index] = get(i)
1026
- if index < n-1
1027
- perms[index+1]
1028
- else
1029
- yield result.dup
1030
- end
1031
- end
1032
- end
1033
- perms[0]
1034
- end
1035
- self
1036
- end
1037
-
1038
- # Cartesian product or multiplication.
1039
- #
1040
- # @overload product(*vectors)
1041
- # Return a `Vector` of all combinations of elements from this `Vector` and each
1042
- # of the given vectors or arrays. The length of the returned `Vector` is the product
1043
- # of `self.size` and the size of each argument vector or array.
1044
- # @example
1045
- # v1 = Immutable::Vector[1, 2, 3]
1046
- # v2 = Immutable::Vector["A", "B"]
1047
- # v1.product(v2)
1048
- # # => [[1, "A"], [1, "B"], [2, "A"], [2, "B"], [3, "A"], [3, "B"]]
1049
- # @overload product
1050
- # Return the result of multiplying all the items in this `Vector` together.
1051
- #
1052
- # @example
1053
- # Immutable::Vector[1, 2, 3, 4, 5].product # => 120
1054
- #
1055
- # @return [Vector]
1056
- def product(*vectors)
1057
- # if no vectors passed, return "product" as in result of multiplying all items
1058
- return super if vectors.empty?
1059
-
1060
- vectors.unshift(self)
1061
-
1062
- if vectors.any?(&:empty?)
1063
- return block_given? ? self : []
1064
- end
1065
-
1066
- counters = Array.new(vectors.size, 0)
1067
-
1068
- bump_counters = lambda do
1069
- i = vectors.size-1
1070
- counters[i] += 1
1071
- while counters[i] == vectors[i].size
1072
- counters[i] = 0
1073
- i -= 1
1074
- return true if i == -1 # we are done
1075
- counters[i] += 1
1076
- end
1077
- false # not done yet
1078
- end
1079
- build_array = lambda do
1080
- array = []
1081
- counters.each_with_index { |index,i| array << vectors[i][index] }
1082
- array
1083
- end
1084
-
1085
- if block_given?
1086
- loop do
1087
- yield build_array[]
1088
- return self if bump_counters[]
1089
- end
1090
- else
1091
- result = []
1092
- loop do
1093
- result << build_array[]
1094
- return result if bump_counters[]
1095
- end
1096
- end
1097
- end
1098
-
1099
- # Assume all elements are vectors or arrays and transpose the rows and columns.
1100
- # In other words, take the first element of each nested vector/array and gather
1101
- # them together into a new `Vector`. Do likewise for the second, third, and so on
1102
- # down to the end of each nested vector/array. Gather all the resulting `Vectors`
1103
- # into a new `Vector` and return it.
1104
- #
1105
- # This operation is closely related to {#zip}. The result is almost the same as
1106
- # calling {#zip} on the first nested vector/array with the others supplied as
1107
- # arguments.
1108
- #
1109
- # @example
1110
- # Immutable::Vector[["A", 10], ["B", 20], ["C", 30]].transpose
1111
- # # => Immutable::Vector[Immutable::Vector["A", "B", "C"], Immutable::Vector[10, 20, 30]]
1112
- #
1113
- # @return [Vector]
1114
- # @raise [IndexError] if elements are not of the same size.
1115
- # @raise [TypeError] if an element does not respond to #size and #[]
1116
- def transpose
1117
- return self.class.empty if empty?
1118
- result = Array.new(first.size) { [] }
1119
-
1120
- 0.upto(@size-1) do |i|
1121
- source = get(i)
1122
- if source.size != result.size
1123
- raise IndexError, "element size differs (#{source.size} should be #{result.size})"
1124
- end
1125
-
1126
- 0.upto(result.size-1) do |j|
1127
- result[j].push(source[j])
1128
- end
1129
- end
1130
-
1131
- result.map! { |a| self.class.new(a) }
1132
- self.class.new(result)
1133
- rescue NoMethodError
1134
- if any? { |x| !x.respond_to?(:size) || !x.respond_to?(:[]) }
1135
- bad = find { |x| !x.respond_to?(:size) || !x.respond_to?(:[]) }
1136
- raise TypeError, "'#{bad.inspect}' must respond to #size and #[] to be transposed"
1137
- else
1138
- raise
1139
- end
1140
- end
1141
-
1142
- # Finds a value from this `Vector` which meets the condition defined by the
1143
- # provided block, using a binary search. The vector must already be sorted
1144
- # with respect to the block. See Ruby's `Array#bsearch` for details,
1145
- # behaviour is equivalent.
1146
- #
1147
- # @example
1148
- # v = Immutable::Vector[1, 3, 5, 7, 9, 11, 13]
1149
- # # Block returns true/false for exact element match:
1150
- # v.bsearch { |e| e > 4 } # => 5
1151
- # # Block returns number to match an element in 4 <= e <= 7:
1152
- # v.bsearch { |e| 1 - e / 4 } # => 7
1153
- #
1154
- # @yield Once for at most `log n` elements, where `n` is the size of the
1155
- # vector. The exact elements and ordering are undefined.
1156
- # @yieldreturn [Boolean] `true` if this element matches the criteria, `false` otherwise.
1157
- # @yieldreturn [Integer] See `Array#bsearch` for details.
1158
- # @yieldparam [Object] element element to be evaluated
1159
- # @return [Object] The matched element, or `nil` if none found.
1160
- # @raise TypeError if the block returns a non-numeric, non-boolean, non-nil
1161
- # value.
1162
- def bsearch
1163
- return enum_for(:bsearch) if not block_given?
1164
- low, high, result = 0, @size, nil
1165
- while low < high
1166
- mid = (low + ((high - low) >> 1))
1167
- val = get(mid)
1168
- v = yield val
1169
- if v.is_a? Numeric
1170
- if v == 0
1171
- return val
1172
- elsif v > 0
1173
- high = mid
1174
- else
1175
- low = mid + 1
1176
- end
1177
- elsif v == true
1178
- result = val
1179
- high = mid
1180
- elsif !v
1181
- low = mid + 1
1182
- else
1183
- raise TypeError, "wrong argument type #{v.class} (must be numeric, true, false, or nil)"
1184
- end
1185
- end
1186
- result
1187
- end
1188
-
1189
- # Return an empty `Vector` instance, of the same class as this one. Useful if you
1190
- # have multiple subclasses of `Vector` and want to treat them polymorphically.
1191
- #
1192
- # @return [Vector]
1193
- def clear
1194
- self.class.empty
1195
- end
1196
-
1197
- # Return a randomly chosen item from this `Vector`. If the vector is empty, return `nil`.
1198
- #
1199
- # @example
1200
- # Immutable::Vector[1, 2, 3, 4, 5].sample # => 2
1201
- #
1202
- # @return [Object]
1203
- def sample
1204
- get(rand(@size))
1205
- end
1206
-
1207
- # Return a new `Vector` with only the elements at the given `indices`, in the
1208
- # order specified by `indices`. If any of the `indices` do not exist, `nil`s will
1209
- # appear in their places.
1210
- #
1211
- # @example
1212
- # v = Immutable::Vector["A", "B", "C", "D", "E", "F"]
1213
- # v.values_at(2, 4, 5) # => Immutable::Vector["C", "E", "F"]
1214
- #
1215
- # @param indices [Array] The indices to retrieve and gather into a new `Vector`
1216
- # @return [Vector]
1217
- def values_at(*indices)
1218
- self.class.new(indices.map { |i| get(i) }.freeze)
1219
- end
1220
-
1221
- # Find the index of an element, starting from the end of the vector.
1222
- # Returns `nil` if no element is found.
1223
- #
1224
- # @overload rindex(obj)
1225
- # Return the index of the last element which is `#==` to `obj`.
1226
- #
1227
- # @example
1228
- # v = Immutable::Vector[7, 8, 9, 7, 8, 9]
1229
- # v.rindex(8) # => 4
1230
- #
1231
- # @overload rindex
1232
- # Return the index of the last element for which the block returns true.
1233
- #
1234
- # @yield [element] Once for each element, last to first, until the block
1235
- # returns true.
1236
- # @example
1237
- # v = Immutable::Vector[7, 8, 9, 7, 8, 9]
1238
- # v.rindex { |e| e.even? } # => 4
1239
- #
1240
- # @return [Integer]
1241
- def rindex(obj = (missing_arg = true))
1242
- i = @size - 1
1243
- if missing_arg
1244
- if block_given?
1245
- reverse_each { |item| return i if yield item; i -= 1 }
1246
- nil
1247
- else
1248
- enum_for(:rindex)
1249
- end
1250
- else
1251
- reverse_each { |item| return i if item == obj; i -= 1 }
1252
- nil
1253
- end
1254
- end
1255
-
1256
- # Assumes all elements are nested, indexable collections, and searches through them,
1257
- # comparing `obj` with the first element of each nested collection. Return the
1258
- # first nested collection which matches, or `nil` if none is found.
1259
- # Behaviour is undefined when elements do not meet assumptions (i.e. are
1260
- # not indexable collections).
1261
- #
1262
- # @example
1263
- # v = Immutable::Vector[["A", 10], ["B", 20], ["C", 30]]
1264
- # v.assoc("B") # => ["B", 20]
1265
- #
1266
- # @param obj [Object] The object to search for
1267
- # @return [Object]
1268
- def assoc(obj)
1269
- each do |array|
1270
- next if !array.respond_to?(:[])
1271
- return array if obj == array[0]
1272
- end
1273
- nil
1274
- end
1275
-
1276
- # Assumes all elements are nested, indexable collections, and searches through them,
1277
- # comparing `obj` with the second element of each nested collection. Return
1278
- # the first nested collection which matches, or `nil` if none is found.
1279
- # Behaviour is undefined when elements do not meet assumptions (i.e. are
1280
- # not indexable collections).
1281
- #
1282
- # @example
1283
- # v = Immutable::Vector[["A", 10], ["B", 20], ["C", 30]]
1284
- # v.rassoc(20) # => ["B", 20]
1285
- #
1286
- # @param obj [Object] The object to search for
1287
- # @return [Object]
1288
- def rassoc(obj)
1289
- each do |array|
1290
- next if !array.respond_to?(:[])
1291
- return array if obj == array[1]
1292
- end
1293
- nil
1294
- end
1295
-
1296
- # Return an `Array` with the same elements, in the same order. The returned
1297
- # `Array` may or may not be frozen.
1298
- #
1299
- # @return [Array]
1300
- def to_a
1301
- if @levels == 0
1302
- # When initializing a Vector with 32 or less items, we always make
1303
- # sure @root is frozen, so we can return it directly here
1304
- @root
1305
- else
1306
- flatten_node(@root, @levels * BITS_PER_LEVEL, [])
1307
- end
1308
- end
1309
- alias to_ary to_a
1310
-
1311
- # Return true if `other` has the same type and contents as this `Vector`.
1312
- #
1313
- # @param other [Object] The collection to compare with
1314
- # @return [Boolean]
1315
- def eql?(other)
1316
- return true if other.equal?(self)
1317
- return false unless instance_of?(other.class) && @size == other.size
1318
- @root.eql?(other.instance_variable_get(:@root))
1319
- end
1320
-
1321
- # See `Object#hash`.
1322
- # @return [Integer]
1323
- def hash
1324
- reduce(0) { |hash, item| (hash << 5) - hash + item.hash }
1325
- end
1326
-
1327
- # Return `self`. Since this is an immutable object duplicates are
1328
- # equivalent.
1329
- # @return [Vector]
1330
- def dup
1331
- self
1332
- end
1333
- alias clone dup
1334
-
1335
- # @return [::Array]
1336
- # @private
1337
- def marshal_dump
1338
- to_a
1339
- end
1340
-
1341
- # @private
1342
- def marshal_load(array)
1343
- initialize(array.freeze)
1344
- end
1345
-
1346
- private
1347
-
1348
- def traverse_depth_first(node, level, &block)
1349
- return node.each(&block) if level == 0
1350
- node.each { |child| traverse_depth_first(child, level - 1, &block) }
1351
- end
1352
-
1353
- def reverse_traverse_depth_first(node, level, &block)
1354
- return node.reverse_each(&block) if level == 0
1355
- node.reverse_each { |child| reverse_traverse_depth_first(child, level - 1, &block) }
1356
- end
1357
-
1358
- def leaf_node_for(node, bitshift, index)
1359
- while bitshift > 0
1360
- node = node[(index >> bitshift) & INDEX_MASK]
1361
- bitshift -= BITS_PER_LEVEL
1362
- end
1363
- node
1364
- end
1365
-
1366
- def update_root(index, item)
1367
- root, levels = @root, @levels
1368
- while index >= (1 << (BITS_PER_LEVEL * (levels + 1)))
1369
- root = [root].freeze
1370
- levels += 1
1371
- end
1372
- new_root = update_leaf_node(root, levels * BITS_PER_LEVEL, index, item)
1373
- if new_root.equal?(root)
1374
- self
1375
- else
1376
- self.class.alloc(new_root, @size > index ? @size : index + 1, levels)
1377
- end
1378
- end
1379
-
1380
- def update_leaf_node(node, bitshift, index, item)
1381
- slot_index = (index >> bitshift) & INDEX_MASK
1382
- if bitshift > 0
1383
- old_child = node[slot_index] || []
1384
- item = update_leaf_node(old_child, bitshift - BITS_PER_LEVEL, index, item)
1385
- end
1386
- existing_item = node[slot_index]
1387
- if existing_item.equal?(item)
1388
- node
1389
- else
1390
- node.dup.tap { |n| n[slot_index] = item }.freeze
1391
- end
1392
- end
1393
-
1394
- def flatten_range(node, bitshift, from, to)
1395
- from_slot = (from >> bitshift) & INDEX_MASK
1396
- to_slot = (to >> bitshift) & INDEX_MASK
1397
-
1398
- if bitshift == 0 # are we at the bottom?
1399
- node.slice(from_slot, to_slot-from_slot+1)
1400
- elsif from_slot == to_slot
1401
- flatten_range(node[from_slot], bitshift - BITS_PER_LEVEL, from, to)
1402
- else
1403
- # the following bitmask can be used to pick out the part of the from/to indices
1404
- # which will be used to direct path BELOW this node
1405
- mask = ((1 << bitshift) - 1)
1406
- result = []
1407
-
1408
- if from & mask == 0
1409
- flatten_node(node[from_slot], bitshift - BITS_PER_LEVEL, result)
1410
- else
1411
- result.concat(flatten_range(node[from_slot], bitshift - BITS_PER_LEVEL, from, from | mask))
1412
- end
1413
-
1414
- (from_slot+1).upto(to_slot-1) do |slot_index|
1415
- flatten_node(node[slot_index], bitshift - BITS_PER_LEVEL, result)
1416
- end
1417
-
1418
- if to & mask == mask
1419
- flatten_node(node[to_slot], bitshift - BITS_PER_LEVEL, result)
1420
- else
1421
- result.concat(flatten_range(node[to_slot], bitshift - BITS_PER_LEVEL, to & ~mask, to))
1422
- end
1423
-
1424
- result
1425
- end
1426
- end
1427
-
1428
- def flatten_node(node, bitshift, result)
1429
- if bitshift == 0
1430
- result.concat(node)
1431
- elsif bitshift == BITS_PER_LEVEL
1432
- node.each { |a| result.concat(a) }
1433
- else
1434
- bitshift -= BITS_PER_LEVEL
1435
- node.each { |a| flatten_node(a, bitshift, result) }
1436
- end
1437
- result
1438
- end
1439
-
1440
- def subsequence(from, length)
1441
- return nil if from > @size || from < 0 || length < 0
1442
- length = @size - from if @size < from + length
1443
- return self.class.empty if length == 0
1444
- self.class.new(flatten_range(@root, @levels * BITS_PER_LEVEL, from, from + length - 1))
1445
- end
1446
-
1447
- def flatten_suffix(node, bitshift, from, result)
1448
- from_slot = (from >> bitshift) & INDEX_MASK
1449
-
1450
- if bitshift == 0
1451
- if from_slot == 0
1452
- result.concat(node)
1453
- else
1454
- result.concat(node.slice(from_slot, 32)) # entire suffix of node. excess length is ignored by #slice
1455
- end
1456
- else
1457
- mask = ((1 << bitshift) - 1)
1458
- if from & mask == 0
1459
- from_slot.upto(node.size-1) do |i|
1460
- flatten_node(node[i], bitshift - BITS_PER_LEVEL, result)
1461
- end
1462
- elsif (child = node[from_slot])
1463
- flatten_suffix(child, bitshift - BITS_PER_LEVEL, from, result)
1464
- (from_slot+1).upto(node.size-1) do |i|
1465
- flatten_node(node[i], bitshift - BITS_PER_LEVEL, result)
1466
- end
1467
- end
1468
- result
1469
- end
1470
- end
1471
-
1472
- def replace_suffix(from, suffix)
1473
- # new suffix can go directly after existing elements
1474
- raise IndexError if from > @size
1475
- root, levels = @root, @levels
1476
-
1477
- if (from >> (BITS_PER_LEVEL * (@levels + 1))) != 0
1478
- # index where new suffix goes doesn't fall within current tree
1479
- # we will need to deepen tree
1480
- root = [root].freeze
1481
- levels += 1
1482
- end
1483
-
1484
- new_size = from + suffix.size
1485
- root = replace_node_suffix(root, levels * BITS_PER_LEVEL, from, suffix)
1486
-
1487
- if !suffix.empty?
1488
- levels.times { suffix = suffix.each_slice(32).to_a }
1489
- root.concat(suffix)
1490
- while root.size > 32
1491
- root = root.each_slice(32).to_a
1492
- levels += 1
1493
- end
1494
- else
1495
- while root.size == 1 && levels > 0
1496
- root = root[0]
1497
- levels -= 1
1498
- end
1499
- end
1500
-
1501
- self.class.alloc(root.freeze, new_size, levels)
1502
- end
1503
-
1504
- def replace_node_suffix(node, bitshift, from, suffix)
1505
- from_slot = (from >> bitshift) & INDEX_MASK
1506
-
1507
- if bitshift == 0
1508
- if from_slot == 0
1509
- suffix.shift(32)
1510
- else
1511
- node.take(from_slot).concat(suffix.shift(32 - from_slot))
1512
- end
1513
- else
1514
- mask = ((1 << bitshift) - 1)
1515
- if from & mask == 0
1516
- if from_slot == 0
1517
- new_node = suffix.shift(32 * (1 << bitshift))
1518
- while bitshift != 0
1519
- new_node = new_node.each_slice(32).to_a
1520
- bitshift -= BITS_PER_LEVEL
1521
- end
1522
- new_node
1523
- else
1524
- result = node.take(from_slot)
1525
- remainder = suffix.shift((32 - from_slot) * (1 << bitshift))
1526
- while bitshift != 0
1527
- remainder = remainder.each_slice(32).to_a
1528
- bitshift -= BITS_PER_LEVEL
1529
- end
1530
- result.concat(remainder)
1531
- end
1532
- elsif (child = node[from_slot])
1533
- result = node.take(from_slot)
1534
- result.push(replace_node_suffix(child, bitshift - BITS_PER_LEVEL, from, suffix))
1535
- remainder = suffix.shift((31 - from_slot) * (1 << bitshift))
1536
- while bitshift != 0
1537
- remainder = remainder.each_slice(32).to_a
1538
- bitshift -= BITS_PER_LEVEL
1539
- end
1540
- result.concat(remainder)
1541
- else
1542
- raise "Shouldn't happen"
1543
- end
1544
- end
1545
- end
1546
- end
1547
-
1548
- # The canonical empty `Vector`. Returned by `Vector[]` when
1549
- # invoked with no arguments; also returned by `Vector.empty`. Prefer using this
1550
- # one rather than creating many empty vectors using `Vector.new`.
1551
- #
1552
- # @private
1553
- EmptyVector = Immutable::Vector.empty
1554
- end
1
+ # Definition of Immutable::Vector is in a separate file to avoid
2
+ # circular dependency warnings
3
+ require 'immutable/_core'