immutable-ruby 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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'