Class: Erlang::Tuple
- Inherits:
-
Object
- Object
- Erlang::Tuple
- Includes:
- Associable, Enumerable
- Defined in:
- lib/erlang/tuple.rb
Overview
A Tuple
is an ordered, integer-indexed collection of objects. Like
Ruby's Array
, Tuple
indexing starts at zero and negative indexes count
back from the end.
Tuple
has a similar interface to Array
. The main difference is methods
that would destructively update an Array
(such as #insert or
#delete_at) instead return new Tuple
s and leave the existing one
unchanged.
Creating New Tuples
Erlang::Tuple.new([:first, :second, :third])
Erlang::Tuple[1, 2, 3, 4, 5]
Retrieving Elements from Tuples
tuple = Erlang::Tuple[1, 2, 3, 4, 5]
tuple[0] # => 1
tuple[-1] # => 5
tuple[0,3] # => Erlang::Tuple[1, 2, 3]
tuple[1..-1] # => Erlang::Tuple[2, 3, 4, 5]
tuple.first # => 1
tuple.last # => 5
Creating Modified Tuples
tuple.add(6) # => Erlang::Tuple[1, 2, 3, 4, 5, 6]
tuple.insert(1, :a, :b) # => Erlang::Tuple[1, :a, :b, 2, 3, 4, 5]
tuple.delete_at(2) # => Erlang::Tuple[1, 2, 4, 5]
tuple + [6, 7] # => Erlang::Tuple[1, 2, 3, 4, 5, 6, 7]
Licensing
Portions taken and modified from https://github.com/hamstergem/hamster
Copyright (c) 2009-2014 Simon Harris
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Instance Attribute Summary collapse
-
#size ⇒ Integer
(also: #arity, #length)
readonly
Return the number of elements in this
Tuple
.
Class Method Summary collapse
-
.[](*elements) ⇒ Tuple
Create a new
Tuple
populated with the given elements. - .compare(a, b) ⇒ Object
-
.empty ⇒ Tuple
Return an empty
Tuple
.
Instance Method Summary collapse
-
#*(times) ⇒ Tuple
Repetition.
-
#+(other) ⇒ Tuple
(also: #concat)
Return a new
Tuple
built by concatenating this one withother
. -
#add(element) ⇒ Tuple
(also: #<<, #push)
Return a new
Tuple
withelement
added after the last occupied position. -
#assoc(obj) ⇒ Object
Assumes all elements are nested, indexable collections, and searches through them, comparing
obj
with the first element of each nested collection. -
#bsearch {|element| ... } ⇒ Object
Finds a value from this
Tuple
which meets the condition defined by the provided block, using a binary search. -
#clear ⇒ Tuple
Return an empty
Tuple
instance, of the same class as this one. -
#combination(n) ⇒ self, Enumerator
When invoked with a block, yields all combinations of length
n
of elements from theTuple
, and then returnsself
. -
#delete(obj) ⇒ Tuple
Return a new
Tuple
with all elements which are equal toobj
removed. -
#delete_at(index) ⇒ Tuple
Return a new
Tuple
with the element atindex
removed. -
#drop(n) ⇒ Tuple
Drop the first
n
elements and return the rest in a newTuple
. -
#drop_while ⇒ Tuple, Enumerator
Drop elements up to, but not including, the first element for which the block returns
nil
orfalse
. -
#each(&block) ⇒ self, Enumerator
Call the given block once for each element in the tuple, passing each element from first to last successively to the block.
-
#empty? ⇒ Boolean
Return
true
if thisTuple
contains no elements. -
#eql?(other) ⇒ Boolean
(also: #==)
Return true if
other
has the same type and contents as thisTuple
. -
#erlang_inspect(raw = false) ⇒ String
Allows this
Tuple
to be printed usingErlang.inspect()
. -
#fetch(index, default = (missing_default = true)) ⇒ Object
Retrieve the value at
index
with optional default. -
#fill(object, index = 0, length = nil) ⇒ Tuple
Replace a range of indexes with the given object.
-
#first ⇒ Object
Return the first element in the
Tuple
. -
#flat_map ⇒ Tuple
Return a new
Tuple
with the concatenated results of running the block once for every element in thisTuple
. -
#flatten(level = -1)) ⇒ Tuple
Return a new
Tuple
with all nested tuples and arrays recursively "flattened out". -
#get(index) ⇒ Object
(also: #at)
Retrieve the element at
index
. -
#hash ⇒ Integer
See
Object#hash
. -
#initialize(elements = [].freeze) ⇒ Tuple
constructor
A new instance of Tuple.
-
#insert(index, *elements) ⇒ Tuple
Return a new
Tuple
with the given values inserted before the element atindex
. -
#last ⇒ Object
Return the last element in the
Tuple
. -
#map ⇒ Tuple, Enumerator
(also: #collect)
Invoke the given block once for each element in the tuple, and return a new
Tuple
containing the values returned by the block. -
#permutation(n = @size) ⇒ self, Enumerator
Yields all permutations of length
n
of elements from theTuple
, and then returnsself
. -
#pop ⇒ Tuple
Return a new
Tuple
with the last element removed. -
#product(*tuples) ⇒ Tuple
Cartesian product or multiplication.
-
#put(index, element = yield(get(index))) ⇒ Tuple
(also: #set)
Return a new
Tuple
with a new value at the givenindex
. -
#rassoc(obj) ⇒ Object
Assumes all elements are nested, indexable collections, and searches through them, comparing
obj
with the second element of each nested collection. -
#repeated_combination(n) ⇒ self, Enumerator
When invoked with a block, yields all repeated combinations of length
n
of tuples from theTuple
, and then returnsself
. -
#repeated_permutation(n = @size) ⇒ self, Enumerator
When invoked with a block, yields all repeated permutations of length
n
of elements from theTuple
, and then returnsself
. -
#reverse ⇒ Tuple
Return a new
Tuple
with the same elements as this one, but in reverse order. -
#reverse_each(&block) ⇒ self
Call the given block once for each element in the tuple, from last to first.
-
#rindex(obj = (missing_arg = true)) ⇒ Integer
Find the index of an element, starting from the end of the tuple.
-
#rotate(count = 1) ⇒ Tuple
Return a new
Tuple
with the same elements, but rotated so that the one at indexcount
is the first element of the new tuple. -
#sample ⇒ Object
Return a randomly chosen element from this
Tuple
. -
#select {|element| ... } ⇒ Tuple
(also: #find_all, #keep_if)
Return a new
Tuple
containing all elements for which the given block returns true. -
#shift ⇒ Tuple
Return a new
Tuple
with the first element removed. -
#shuffle ⇒ Tuple
Return a new
Tuple
with the same elements as this one, but randomly permuted. -
#slice(arg, length = (missing_length = true)) ⇒ Object
(also: #[])
Return specific objects from the
Tuple
. -
#sort(&comparator) ⇒ Tuple
Return a new
Tuple
with the same elements, but sorted. -
#sort_by {|element| ... } ⇒ Tuple
Return a new
Tuple
with the same elements, but sorted. -
#take(n) ⇒ Tuple
Return only the first
n
elements in a newTuple
. -
#take_while ⇒ Tuple, Enumerator
Gather elements up to, but not including, the first element for which the block returns
nil
orfalse
, and return them in a newTuple
. -
#to_a ⇒ Array
(also: #to_ary)
Return an
Array
with the same elements, in the same order. -
#transpose ⇒ Tuple
Assume all elements are tuples or arrays and transpose the rows and columns.
-
#uniq(&block) ⇒ Tuple
Return a new
Tuple
with no duplicate elements, as determined by#hash
and#eql?
. -
#unshift(object) ⇒ Tuple
Return a new
Tuple
withobject
inserted before the first element, moving the other elements upwards. -
#update_in(*key_path) {|value| ... } ⇒ Tuple
Return a new
Tuple
with a deeply nested value modified to the result of the given code block. -
#values_at(*indices) ⇒ Tuple
Return a new
Tuple
with only the elements at the givenindices
, in the order specified byindices
. -
#zip(*others) ⇒ Tuple
Combine two tuples by "zipping" them together.
Methods included from Associable
Methods included from Enumerable
#compact, #each_index, #grep, #grep_v, #group_by, #inspect, #join, #partition, #reject, #sum
Constructor Details
#initialize(elements = [].freeze) ⇒ Tuple
Returns a new instance of Tuple.
120 121 122 123 124 125 126 127 128 129 130 131 132 133 |
# File 'lib/erlang/tuple.rb', line 120 def initialize(elements=[].freeze) elements = elements.to_a.map { |element| Erlang.from(element) } if elements.size <= 32 elements = elements.dup.freeze if !elements.frozen? @root, @size, @levels = elements, elements.size, 0 else root, size, levels = elements, elements.size, 0 while root.size > 32 root = root.each_slice(32).to_a levels += 1 end @root, @size, @levels = root.freeze, size, levels end end |
Instance Attribute Details
#size ⇒ Integer (readonly) Also known as: arity, length
Return the number of elements in this Tuple
75 76 77 |
# File 'lib/erlang/tuple.rb', line 75 def size @size end |
Class Method Details
.[](*elements) ⇒ Tuple
Create a new Tuple
populated with the given elements.
82 83 84 |
# File 'lib/erlang/tuple.rb', line 82 def [](*elements) return new(elements.freeze) end |
.compare(a, b) ⇒ Object
107 108 109 110 111 112 113 114 115 116 117 |
# File 'lib/erlang/tuple.rb', line 107 def compare(a, b) raise ArgumentError, "'a' must be of Erlang::Tuple type" if not a.kind_of?(Erlang::Tuple) raise ArgumentError, "'b' must be of Erlang::Tuple type" if not b.kind_of?(Erlang::Tuple) c = a.size <=> b.size i = 0 while c == 0 and i < a.size and i < b.size c = Erlang.compare(a[i], b[i]) i += 1 end return c end |
.empty ⇒ Tuple
Return an empty Tuple
. If used on a subclass, returns an empty instance
of that class.
90 91 92 |
# File 'lib/erlang/tuple.rb', line 90 def empty return @empty ||= self.new end |
Instance Method Details
#*(times) ⇒ Tuple
Repetition. Return a new Tuple
built by concatenating times
copies
of this one together.
806 807 808 809 810 811 |
# File 'lib/erlang/tuple.rb', line 806 def *(times) return self.class.empty if times == 0 return self if times == 1 result = (to_a * times) return result.is_a?(Array) ? self.class.new(result) : result end |
#+(other) ⇒ Tuple Also known as: concat
Return a new Tuple
built by concatenating this one with other
. other
can be any object which is convertible to an Array
using #to_a
.
652 653 654 655 656 657 |
# File 'lib/erlang/tuple.rb', line 652 def +(other) other = Erlang.from(other) other = other.to_a other = other.dup if other.frozen? return replace_suffix(@size, other) end |
#add(element) ⇒ Tuple Also known as: <<, push
Return a new Tuple
with element
added after the last occupied position.
169 170 171 |
# File 'lib/erlang/tuple.rb', line 169 def add(element) return update_root(@size, Erlang.from(element)) end |
#assoc(obj) ⇒ Object
Assumes all elements are nested, indexable collections, and searches through them,
comparing obj
with the first element of each nested collection. Return the
first nested collection which matches, or nil
if none is found.
Behaviour is undefined when elements do not meet assumptions (i.e. are
not indexable collections).
1294 1295 1296 1297 1298 1299 1300 1301 |
# File 'lib/erlang/tuple.rb', line 1294 def assoc(obj) obj = Erlang.from(obj) each do |array| next if !array.respond_to?(:[]) return array if obj == array[0] end return nil end |
#bsearch {|element| ... } ⇒ Object
Finds a value from this Tuple
which meets the condition defined by the
provided block, using a binary search. The tuple must already be sorted
with respect to the block. See Ruby's Array#bsearch
for details,
behaviour is equivalent.
1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 |
# File 'lib/erlang/tuple.rb', line 1187 def bsearch return enum_for(:bsearch) if not block_given? low, high, result = 0, @size, nil while low < high mid = (low + ((high - low) >> 1)) val = get(mid) v = yield val if v.is_a? Numeric if v == 0 return val elsif v > 0 high = mid else low = mid + 1 end elsif v == true result = val high = mid elsif !v low = mid + 1 else raise TypeError, "wrong argument type #{v.class} (must be numeric, true, false, or nil)" end end return result end |
#clear ⇒ Tuple
Return an empty Tuple
instance, of the same class as this one. Useful if you
have multiple subclasses of Tuple
and want to treat them polymorphically.
1218 1219 1220 |
# File 'lib/erlang/tuple.rb', line 1218 def clear return self.class.empty end |
#combination(n) ⇒ self, Enumerator
When invoked with a block, yields all combinations of length n
of elements
from the Tuple
, and then returns self
. There is no guarantee about
which order the combinations will be yielded.
If no block is given, an Enumerator
is returned instead.
886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 |
# File 'lib/erlang/tuple.rb', line 886 def combination(n) return enum_for(:combination, n) if not block_given? return self if n < 0 || @size < n if n == 0 yield [] elsif n == 1 each { |element| yield [element] } elsif n == @size yield self.to_a else combos = lambda do |result,index,remaining| while @size - index > remaining if remaining == 1 yield result.dup << get(index) else combos[result.dup << get(index), index+1, remaining-1] end index += 1 end index.upto(@size-1) { |i| result << get(i) } yield result end combos[[], 0, n] end return self end |
#delete(obj) ⇒ Tuple
Return a new Tuple
with all elements which are equal to obj
removed.
#==
is used for checking equality.
516 517 518 519 |
# File 'lib/erlang/tuple.rb', line 516 def delete(obj) obj = Erlang.from(obj) return select { |element| element != obj } end |
#delete_at(index) ⇒ Tuple
Return a new Tuple
with the element at index
removed. If the given index
does not exist, return self
.
412 413 414 415 416 417 418 |
# File 'lib/erlang/tuple.rb', line 412 def delete_at(index) return self if index >= @size || index < -@size index += @size if index < 0 suffix = flatten_suffix(@root, @levels * BITS_PER_LEVEL, index, []) return replace_suffix(index, suffix.tap { |a| a.shift }) end |
#drop(n) ⇒ Tuple
Drop the first n
elements and return the rest in a new Tuple
.
749 750 751 752 753 754 |
# File 'lib/erlang/tuple.rb', line 749 def drop(n) return self if n == 0 return self.class.empty if n >= @size raise ArgumentError, "attempt to drop negative size" if n < 0 return self.class.new(flatten_suffix(@root, @levels * BITS_PER_LEVEL, n, [])) end |
#drop_while ⇒ Tuple, Enumerator
Drop elements up to, but not including, the first element for which the
block returns nil
or false
. Gather the remaining elements into a new
Tuple
. If no block is given, an Enumerator
is returned instead.
778 779 780 781 |
# File 'lib/erlang/tuple.rb', line 778 def drop_while return enum_for(:drop_while) if not block_given? return self.class.new(super) end |
#each(&block) ⇒ self, Enumerator
Call the given block once for each element in the tuple, passing each
element from first to last successively to the block. If no block is given,
an Enumerator
is returned instead.
469 470 471 472 473 |
# File 'lib/erlang/tuple.rb', line 469 def each(&block) return to_enum unless block_given? traverse_depth_first(@root, @levels, &block) return self end |
#empty? ⇒ Boolean
Return true
if this Tuple
contains no elements.
138 139 140 |
# File 'lib/erlang/tuple.rb', line 138 def empty? return @size == 0 end |
#eql?(other) ⇒ Boolean Also known as: ==
Return true if other
has the same type and contents as this Tuple
.
1343 1344 1345 1346 1347 1348 1349 1350 1351 |
# File 'lib/erlang/tuple.rb', line 1343 def eql?(other) return true if other.equal?(self) if instance_of?(other.class) return false if @size != other.size return @root.eql?(other.instance_variable_get(:@root)) else return !!(Erlang.compare(other, self) == 0) end end |
#erlang_inspect(raw = false) ⇒ String
Allows this Tuple
to be printed using Erlang.inspect()
.
1376 1377 1378 1379 1380 1381 |
# File 'lib/erlang/tuple.rb', line 1376 def erlang_inspect(raw = false) result = '{' each_with_index { |obj, i| result << ',' if i > 0; result << Erlang.inspect(obj, raw: raw) } result << '}' return result end |
#fetch(index) ⇒ Object #fetch(index) {|index| ... } ⇒ Object #fetch(index, default) ⇒ Object
Retrieve the value at index
with optional default.
298 299 300 301 302 303 304 305 306 307 308 |
# File 'lib/erlang/tuple.rb', line 298 def fetch(index, default = (missing_default = true)) if index >= -@size && index < @size return get(index) elsif block_given? return Erlang.from(yield(index)) elsif !missing_default return Erlang.from(default) else raise IndexError, "index #{index} outside of tuple bounds" end end |
#fill(object) ⇒ Tuple #fill(object, index) ⇒ Tuple #fill(object, index, length) ⇒ Tuple
Replace a range of indexes with the given object.
850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 |
# File 'lib/erlang/tuple.rb', line 850 def fill(object, index = 0, length = nil) raise IndexError if index < -@size object = Erlang.from(object) index += @size if index < 0 length ||= @size - index # to the end of the array, if no length given if index < @size suffix = flatten_suffix(@root, @levels * BITS_PER_LEVEL, index, []) suffix.fill(object, 0, length) elsif index == @size suffix = Array.new(length, object) else suffix = Array.new(index - @size, nil).concat(Array.new(length, object)) index = @size end return replace_suffix(index, suffix) end |
#first ⇒ Object
Return the first element in the Tuple
. If the tuple is empty, return nil
.
148 149 150 |
# File 'lib/erlang/tuple.rb', line 148 def first return get(0) end |
#flat_map ⇒ Tuple
Return a new Tuple
with the concatenated results of running the block once
for every element in this Tuple
.
544 545 546 547 548 |
# File 'lib/erlang/tuple.rb', line 544 def flat_map return enum_for(:flat_map) if not block_given? return self if empty? return self.class.new(super) end |
#flatten(level = -1)) ⇒ Tuple
Return a new Tuple
with all nested tuples and arrays recursively "flattened
out". That is, their elements inserted into the new Tuple
in the place where
the nested array/tuple originally was. If an optional level
argument is
provided, the flattening will only be done recursively that number of times.
A level
of 0 means not to flatten at all, 1 means to only flatten nested
arrays/tuples which are directly contained within this Tuple
.
631 632 633 634 635 636 637 638 639 640 641 |
# File 'lib/erlang/tuple.rb', line 631 def flatten(level = -1) return self if level == 0 array = self.to_a if array.frozen? return self.class.new(array.flatten(level).freeze) elsif array.flatten!(level) # returns nil if no changes were made return self.class.new(array.freeze) else return self end end |
#get(index) ⇒ Object Also known as: at
Retrieve the element at index
. If there is none (either the provided index
is too high or too low), return nil
.
251 252 253 254 255 256 |
# File 'lib/erlang/tuple.rb', line 251 def get(index) return nil if @size == 0 index += @size if index < 0 return nil if index >= @size || index < 0 return leaf_node_for(@root, @levels * BITS_PER_LEVEL, index)[index & INDEX_MASK] end |
#hash ⇒ Integer
See Object#hash
.
1356 1357 1358 |
# File 'lib/erlang/tuple.rb', line 1356 def hash return reduce(Erlang::Tuple.hash) { |hash, item| (hash << 5) - hash + item.hash } end |
#insert(index, *elements) ⇒ Tuple
Return a new Tuple
with the given values inserted before the element
at index
. If index
is greater than the current length, nil
values
are added to pad the Tuple
to the required size.
384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 |
# File 'lib/erlang/tuple.rb', line 384 def insert(index, *elements) raise IndexError if index < -@size index += @size if index < 0 elements = elements.map { |element| Erlang.from(element) } if index < @size suffix = flatten_suffix(@root, @levels * BITS_PER_LEVEL, index, []) suffix.unshift(*elements) elsif index == @size suffix = elements else suffix = Array.new(index - @size, nil).concat(elements) index = @size end return replace_suffix(index, suffix) end |
#last ⇒ Object
Return the last element in the Tuple
. If the tuple is empty, return nil
.
158 159 160 |
# File 'lib/erlang/tuple.rb', line 158 def last return get(-1) end |
#map ⇒ Tuple, Enumerator Also known as: collect
Invoke the given block once for each element in the tuple, and return a new
Tuple
containing the values returned by the block. If no block is
provided, return an enumerator.
529 530 531 532 533 |
# File 'lib/erlang/tuple.rb', line 529 def map return enum_for(:map) if not block_given? return self if empty? return self.class.new(super) end |
#permutation(n = @size) ⇒ self, Enumerator
Yields all permutations of length n
of elements from the Tuple
, and then
returns self
. If no length n
is specified, permutations of all elements
will be yielded.
There is no guarantee about which order the permutations will be yielded in.
If no block is given, an Enumerator
is returned instead.
989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 |
# File 'lib/erlang/tuple.rb', line 989 def permutation(n = @size) return enum_for(:permutation, n) if not block_given? if n < 0 || @size < n # yield nothing elsif n == 0 yield [] elsif n == 1 each { |element| yield [element] } else used, result = [], [] perms = lambda do |index| 0.upto(@size-1) do |i| if !used[i] result[index] = get(i) if index < n-1 used[i] = true perms[index+1] used[i] = false else yield result.dup end end end end perms[0] end return self end |
#pop ⇒ Tuple
Return a new Tuple
with the last element removed. Return self
if
empty.
427 428 429 430 |
# File 'lib/erlang/tuple.rb', line 427 def pop return self if @size == 0 return replace_suffix(@size-1, []) end |
#product(*tuples) ⇒ Tuple #product ⇒ Tuple
Cartesian product or multiplication.
1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 |
# File 'lib/erlang/tuple.rb', line 1087 def product(*tuples) tuples = tuples.map { |tuple| Erlang.from(tuple) } # if no tuples passed, return "product" as in result of multiplying all elements return super if tuples.empty? tuples.unshift(self) if tuples.any?(&:empty?) return block_given? ? self : [] end counters = Array.new(tuples.size, 0) bump_counters = lambda do i = tuples.size-1 counters[i] += 1 while counters[i] == tuples[i].size counters[i] = 0 i -= 1 return true if i == -1 # we are done counters[i] += 1 end false # not done yet end build_array = lambda do array = [] counters.each_with_index { |index,i| array << tuples[i][index] } array end if block_given? while true yield build_array[] return self if bump_counters[] end else result = [] while true result << build_array[] return result if bump_counters[] end end end |
#put(index, element) ⇒ Tuple #put(index) {|existing| ... } ⇒ Tuple Also known as: set
Return a new Tuple
with a new value at the given index
. If index
is greater than the length of the tuple, the returned tuple will be
padded with nil
s to the correct size.
202 203 204 205 206 207 208 209 210 211 212 213 |
# File 'lib/erlang/tuple.rb', line 202 def put(index, element = yield(get(index))) raise IndexError, "index #{index} outside of tuple bounds" if index < -@size element = Erlang.from(element) index += @size if index < 0 if index > @size suffix = Array.new(index - @size, nil) suffix << element return replace_suffix(@size, suffix) else return update_root(index, element) end end |
#rassoc(obj) ⇒ Object
Assumes all elements are nested, indexable collections, and searches through them,
comparing obj
with the second element of each nested collection. Return
the first nested collection which matches, or nil
if none is found.
Behaviour is undefined when elements do not meet assumptions (i.e. are
not indexable collections).
1315 1316 1317 1318 1319 1320 1321 1322 |
# File 'lib/erlang/tuple.rb', line 1315 def rassoc(obj) obj = Erlang.from(obj) each do |array| next if !array.respond_to?(:[]) return array if obj == array[1] end return nil end |
#repeated_combination(n) ⇒ self, Enumerator
When invoked with a block, yields all repeated combinations of length n
of
tuples from the Tuple
, and then returns self
. A "repeated combination" is
one in which any tuple from the Tuple
can appear consecutively any number of
times.
There is no guarantee about which order the combinations will be yielded in.
If no block is given, an Enumerator
is returned instead.
939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 |
# File 'lib/erlang/tuple.rb', line 939 def repeated_combination(n) return enum_for(:repeated_combination, n) if not block_given? if n < 0 # yield nothing elsif n == 0 yield [] elsif n == 1 each { |element| yield [element] } elsif @size == 0 # yield nothing else combos = lambda do |result,index,remaining| while index < @size-1 if remaining == 1 yield result.dup << get(index) else combos[result.dup << get(index), index, remaining-1] end index += 1 end element = get(index) remaining.times { result << element } yield result end combos[[], 0, n] end return self end |
#repeated_permutation(n = @size) ⇒ self, Enumerator
When invoked with a block, yields all repeated permutations of length n
of
elements from the Tuple
, and then returns self
. A "repeated permutation" is
one where any element from the Tuple
can appear any number of times, and in
any position (not just consecutively)
If no length n
is specified, permutations of all elements will be yielded.
There is no guarantee about which order the permutations will be yielded in.
If no block is given, an Enumerator
is returned instead.
1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 |
# File 'lib/erlang/tuple.rb', line 1044 def repeated_permutation(n = @size) return enum_for(:repeated_permutation, n) if not block_given? if n < 0 # yield nothing elsif n == 0 yield [] elsif n == 1 each { |element| yield [element] } else result = [] perms = lambda do |index| 0.upto(@size-1) do |i| result[index] = get(i) if index < n-1 perms[index+1] else yield result.dup end end end perms[0] end return self end |
#reverse ⇒ Tuple
Return a new Tuple
with the same elements as this one, but in reverse order.
593 594 595 |
# File 'lib/erlang/tuple.rb', line 593 def reverse return self.class.new(((array = to_a).frozen? ? array.reverse : array.reverse!).freeze) end |
#reverse_each(&block) ⇒ self
Call the given block once for each element in the tuple, from last to first.
486 487 488 489 490 |
# File 'lib/erlang/tuple.rb', line 486 def reverse_each(&block) return enum_for(:reverse_each) unless block_given? reverse_traverse_depth_first(@root, @levels, &block) return self end |
#rindex(obj) ⇒ Integer #rindex {|element| ... } ⇒ Integer
Find the index of an element, starting from the end of the tuple.
Returns nil
if no element is found.
1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 |
# File 'lib/erlang/tuple.rb', line 1266 def rindex(obj = (missing_arg = true)) obj = Erlang.from(obj) i = @size - 1 if missing_arg if block_given? reverse_each { |element| return i if yield element; i -= 1 } return nil else return enum_for(:rindex) end else reverse_each { |element| return i if element == obj; i -= 1 } return nil end end |
#rotate(count = 1) ⇒ Tuple
Return a new Tuple
with the same elements, but rotated so that the one at
index count
is the first element of the new tuple. If count
is positive,
the elements will be shifted left, and those shifted past the lowest position
will be moved to the end. If count
is negative, the elements will be shifted
right, and those shifted past the last position will be moved to the beginning.
610 611 612 613 |
# File 'lib/erlang/tuple.rb', line 610 def rotate(count = 1) return self if (count % @size) == 0 return self.class.new(((array = to_a).frozen? ? array.rotate(count) : array.rotate!(count)).freeze) end |
#sample ⇒ Object
Return a randomly chosen element from this Tuple
. If the tuple is empty, return nil
.
1228 1229 1230 |
# File 'lib/erlang/tuple.rb', line 1228 def sample return get(rand(@size)) end |
#select {|element| ... } ⇒ Tuple Also known as: find_all, keep_if
Return a new Tuple
containing all elements for which the given block returns
true.
501 502 503 504 |
# File 'lib/erlang/tuple.rb', line 501 def select return enum_for(:select) unless block_given? return reduce(self.class.empty) { |tuple, element| yield(element) ? tuple.add(element) : tuple } end |
#shift ⇒ Tuple
Return a new Tuple
with the first element removed. If empty, return
self
.
452 453 454 |
# File 'lib/erlang/tuple.rb', line 452 def shift return delete_at(0) end |
#shuffle ⇒ Tuple
Return a new Tuple
with the same elements as this one, but randomly permuted.
556 557 558 |
# File 'lib/erlang/tuple.rb', line 556 def shuffle return self.class.new(((array = to_a).frozen? ? array.shuffle : array.shuffle!).freeze) end |
#tuple.slice(index) ⇒ Object #tuple.slice(index, length) ⇒ Tuple #tuple.slice(index..end) ⇒ Tuple Also known as: []
Return specific objects from the Tuple
. All overloads return nil
if
the starting index is out of range.
350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 |
# File 'lib/erlang/tuple.rb', line 350 def slice(arg, length = (missing_length = true)) if missing_length if arg.is_a?(Range) from, to = arg.begin, arg.end from += @size if from < 0 to += @size if to < 0 to += 1 if !arg.exclude_end? length = to - from length = 0 if length < 0 return subsequence(from, length) else return get(arg) end else arg += @size if arg < 0 return subsequence(arg, length) end end |
#sort ⇒ Tuple #sort {|a, b| ... } ⇒ Tuple
Return a new Tuple
with the same elements, but sorted.
715 716 717 718 719 |
# File 'lib/erlang/tuple.rb', line 715 def sort(&comparator) comparator = Erlang.method(:compare) unless block_given? array = super(&comparator) return self.class.new(array) end |
#sort_by {|element| ... } ⇒ Tuple
Return a new Tuple
with the same elements, but sorted. The sort order is
determined by mapping the elements through the given block to obtain sort
keys, and then sorting the keys according to their natural sort order
(#<=>
).
733 734 735 736 737 738 |
# File 'lib/erlang/tuple.rb', line 733 def sort_by return sort unless block_given? block = ->(x) { Erlang.from(transformer.call(x)) } array = super(&block) return self.class.new(array) end |
#take(n) ⇒ Tuple
Return only the first n
elements in a new Tuple
.
764 765 766 767 |
# File 'lib/erlang/tuple.rb', line 764 def take(n) return self if n >= @size return self.class.new(super) end |
#take_while ⇒ Tuple, Enumerator
Gather elements up to, but not including, the first element for which the
block returns nil
or false
, and return them in a new Tuple
. If no block
is given, an Enumerator
is returned instead.
792 793 794 795 |
# File 'lib/erlang/tuple.rb', line 792 def take_while return enum_for(:take_while) if not block_given? return self.class.new(super) end |
#to_a ⇒ Array Also known as: to_ary
Return an Array
with the same elements, in the same order. The returned
Array
may or may not be frozen.
1328 1329 1330 1331 1332 1333 1334 1335 1336 |
# File 'lib/erlang/tuple.rb', line 1328 def to_a if @levels == 0 # When initializing a Tuple with 32 or less elements, we always make # sure @root is frozen, so we can return it directly here return @root else return flatten_node(@root, @levels * BITS_PER_LEVEL, []) end end |
#transpose ⇒ Tuple
Assume all elements are tuples or arrays and transpose the rows and columns.
In other words, take the first element of each nested tuple/array and gather
them together into a new Tuple
. Do likewise for the second, third, and so on
down to the end of each nested Tuple/array. Gather all the resulting Tuple
s
into a new Tuple
and return it.
This operation is closely related to #zip. The result is almost the same as calling #zip on the first nested Tuple/array with the others supplied as arguments.
1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 |
# File 'lib/erlang/tuple.rb', line 1148 def transpose return self.class.empty if empty? result = Array.new(first.size) { [] } 0.upto(@size-1) do |i| source = get(i) if source.size != result.size raise IndexError, "element size differs (#{source.size} should be #{result.size})" end 0.upto(result.size-1) do |j| result[j].push(source[j]) end end result.map! { |a| self.class.new(a) } return self.class.new(result) end |
#uniq(&block) ⇒ Tuple
Return a new Tuple
with no duplicate elements, as determined by #hash
and
#eql?
. For each group of equivalent elements, only the first will be retained.
568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 |
# File 'lib/erlang/tuple.rb', line 568 def uniq(&block) array = self.to_a if block_given? if array.frozen? return self.class.new(array.uniq(&block).freeze) elsif array.uniq!(&block) # returns nil if no changes were made return self.class.new(array.freeze) else return self end elsif array.frozen? return self.class.new(array.uniq.freeze) elsif array.uniq! # returns nil if no changes were made return self.class.new(array.freeze) else return self end end |
#unshift(object) ⇒ Tuple
Return a new Tuple
with object
inserted before the first element,
moving the other elements upwards.
441 442 443 |
# File 'lib/erlang/tuple.rb', line 441 def unshift(object) return insert(0, Erlang.from(object)) end |
#update_in(*key_path) {|value| ... } ⇒ Tuple
Return a new Tuple
with a deeply nested value modified to the result
of the given code block. When traversing the nested Tuple
s and
Hash
es, non-existing keys are created with empty Hash
values.
The code block receives the existing value of the deeply nested key (or
nil
if it doesn't exist). This is useful for "transforming" the value
associated with a certain key.
Note that the original Tuple
and sub-Tuple
s and sub-Hash
es are
left unmodified; new data structure copies are created along the path
wherever needed.
|
# File 'lib/erlang/tuple.rb', line 216
|
#values_at(*indices) ⇒ Tuple
Return a new Tuple
with only the elements at the given indices
, in the
order specified by indices
. If any of the indices
do not exist, nil
s will
appear in their places.
1242 1243 1244 |
# File 'lib/erlang/tuple.rb', line 1242 def values_at(*indices) return self.class.new(indices.map { |i| get(i) }.freeze) end |
#zip(*others) ⇒ Tuple #zip(*others) {|pair| ... } ⇒ nil
Combine two tuples by "zipping" them together. others
should be arrays
and/or tuples. The corresponding elements from this Tuple
and each of
others
(that is, the elements with the same indices) will be gathered
into arrays.
If others
contains fewer elements than this tuple, nil
will be used
for padding.
685 686 687 688 689 690 691 692 |
# File 'lib/erlang/tuple.rb', line 685 def zip(*others) others = others.map { |other| Erlang.from(other) } if block_given? return super(*others) else return self.class.new(super(*others)) end end |