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.
- checksums.yaml +4 -4
- data/lib/immutable/_core.rb +3067 -0
- data/lib/immutable/hash.rb +4 -941
- data/lib/immutable/set.rb +3 -583
- data/lib/immutable/sorted_set.rb +0 -2
- data/lib/immutable/vector.rb +3 -1554
- data/lib/immutable/version.rb +1 -1
- metadata +7 -6
data/lib/immutable/vector.rb
CHANGED
@@ -1,1554 +1,3 @@
|
|
1
|
-
|
2
|
-
|
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'
|