Class: Functional::Tuple
- Inherits:
-
Synchronization::Object
- Object
- Synchronization::Object
- Functional::Tuple
- Defined in:
- lib/functional/tuple.rb
Overview
The current implementation uses simple Ruby arrays. This is likely to be very inefficient for all but the smallest tuples. The more items the tuple contains, the less efficient it will become. A future version will use a fast, immutable, persistent data structure such as a finger tree or a trie.
This is a write-once, read-many, thread safe object that can be used in concurrent systems. Thread safety guarantees cannot be made about objects contained within this object, however. Ruby variables are mutable references to mutable objects. This cannot be changed. The best practice it to only encapsulate immutable, frozen, or thread safe objects. Ultimately, thread safety is the responsibility of the programmer.
A tuple is a pure functional data strcture that is similar to an array but is immutable and of fixed length. Tuples support many of the same operations as array/list/vector.
Instance Method Summary collapse
-
#at(index) ⇒ Object
(also: #nth, #[])
Retrieve the item at the given index.
-
#concat(other) ⇒ Functional::Tuple
(also: #+)
Returns a new tuple built by concatenating the two tuples together to produce a third tuple.
-
#diff(other) ⇒ Functional::Tuple
(also: #-)
Returns a new tuple that is a copy of the original tuple, removing any items that also appear in other.
-
#each {|item| ... } ⇒ Enumerable
Calls the given block once for each element in self, passing that element as a parameter.
-
#each_with_index {|item, index| ... } ⇒ Enumerable
Calls the given block once for each element in self, passing that element and the current index as parameters.
-
#empty? ⇒ Boolean
Returns true if self contains no items.
-
#eql?(other) ⇒ Boolean
(also: #==)
Compares this object and other for equality.
-
#fetch(index, default) ⇒ Object
Retrieve the item at the given index or return the given default value if the index is out of bounds.
-
#first ⇒ Object
(also: #head)
Returns the first element of the tuple or nil when empty.
-
#initialize(data = []) ⇒ Tuple
constructor
Create a new tuple with the given data items in the given order.
-
#intersect(other) ⇒ Functional::Tuple
(also: #&)
Returns a new tuple containing elements common to the two tuples, excluding any duplicates.
-
#length ⇒ Fixnum
(also: #size)
The number of items in the tuple.
-
#repeat(multiple) ⇒ Functional::Tuple
(also: #*)
Returns a new tuple built by concatenating the given number of copies of self.
-
#rest ⇒ Functional::Tuple
(also: #tail)
Returns a tuple containing all the items in self after the first item.
-
#sequence {|head, tail| ... } ⇒ Enumerable
Calls the given block once for each element in self, passing that element and a tuple with all the remaining items in the tuple.
-
#to_a ⇒ Array
(also: #to_ary)
Create a standard Ruby mutable array containing the tuple items in the same order.
-
#union(other) ⇒ Functional::Tuple
(also: #|)
Returns a new tuple by joining self with other, excluding any duplicates and preserving the order from the original tuple.
-
#uniq ⇒ Functional::Tuple
Returns a new tuple by removing duplicate values in self.
Constructor Details
#initialize(data = []) ⇒ Tuple
Create a new tuple with the given data items in the given order.
38 39 40 41 42 43 44 |
# File 'lib/functional/tuple.rb', line 38 def initialize(data = []) raise ArgumentError.new('data is not an array') unless data.respond_to?(:to_a) super @data = data.to_a.dup.freeze self.freeze ensure_ivar_visibility! end |
Instance Method Details
#at(index) ⇒ Object Also known as: nth, []
Retrieve the item at the given index. Indices begin at zero and increment up, just like Ruby arrays. Negative indicies begin at -1, which represents the last item in the tuple, and decrement toward the first item. If the given index is out of range then ‘nil` is returned.
53 54 55 |
# File 'lib/functional/tuple.rb', line 53 def at(index) @data[index] end |
#concat(other) ⇒ Functional::Tuple Also known as: +
Returns a new tuple built by concatenating the two tuples together to produce a third tuple.
108 109 110 |
# File 'lib/functional/tuple.rb', line 108 def concat(other) Tuple.new(@data + other.to_a) end |
#diff(other) ⇒ Functional::Tuple Also known as: -
Returns a new tuple that is a copy of the original tuple, removing any items that also appear in other. The order is preserved from the original tuple.
117 118 119 |
# File 'lib/functional/tuple.rb', line 117 def diff(other) Tuple.new(@data - other.to_a) end |
#each {|item| ... } ⇒ Enumerable
Calls the given block once for each element in self, passing that element as a parameter. An Enumerator is returned if no block is given.
147 148 149 150 151 152 |
# File 'lib/functional/tuple.rb', line 147 def each return enum_for(:each) unless block_given? @data.each do |item| yield(item) end end |
#each_with_index {|item, index| ... } ⇒ Enumerable
Calls the given block once for each element in self, passing that element and the current index as parameters. An Enumerator is returned if no block is given.
160 161 162 163 164 165 |
# File 'lib/functional/tuple.rb', line 160 def each_with_index return enum_for(:each_with_index) unless block_given? @data.each_with_index do |item, index| yield(item, index) end end |
#empty? ⇒ Boolean
Returns true if self contains no items.
204 205 206 |
# File 'lib/functional/tuple.rb', line 204 def empty? @data.empty? end |
#eql?(other) ⇒ Boolean Also known as: ==
Compares this object and other for equality. A tuple is ‘eql?` to other when other is a tuple or an array-like object (any object that responds to `to_a`) and the two objects have identical values in the same foxed order.
196 197 198 |
# File 'lib/functional/tuple.rb', line 196 def eql?(other) @data == other.to_a end |
#fetch(index, default) ⇒ Object
Retrieve the item at the given index or return the given default value if the index is out of bounds. The behavior of indicies follows the rules for the ‘at` method.
68 69 70 71 72 73 74 |
# File 'lib/functional/tuple.rb', line 68 def fetch(index, default) if index >= length || -index > length default else at(index) end end |
#first ⇒ Object Also known as: head
Returns the first element of the tuple or nil when empty.
211 212 213 |
# File 'lib/functional/tuple.rb', line 211 def first @data.first end |
#intersect(other) ⇒ Functional::Tuple Also known as: &
Returns a new tuple containing elements common to the two tuples, excluding any duplicates. The order is preserved from the original tuple.
90 91 92 |
# File 'lib/functional/tuple.rb', line 90 def intersect(other) Tuple.new(@data & other.to_a) end |
#length ⇒ Fixnum Also known as: size
The number of items in the tuple.
79 80 81 |
# File 'lib/functional/tuple.rb', line 79 def length @data.length end |
#repeat(multiple) ⇒ Functional::Tuple Also known as: *
Returns a new tuple built by concatenating the given number of copies of self. Returns an empty tuple when the multiple is zero.
128 129 130 131 132 |
# File 'lib/functional/tuple.rb', line 128 def repeat(multiple) multiple = multiple.to_i raise ArgumentError.new('negative argument') if multiple < 0 Tuple.new(@data * multiple) end |
#rest ⇒ Functional::Tuple Also known as: tail
Returns a tuple containing all the items in self after the first item. Returns an empty tuple when empty or there is only one item.
220 221 222 223 224 225 226 |
# File 'lib/functional/tuple.rb', line 220 def rest if @data.length <= 1 Tuple.new else Tuple.new(@data.slice(1..@data.length-1)) end end |
#sequence {|head, tail| ... } ⇒ Enumerable
Calls the given block once for each element in self, passing that element and a tuple with all the remaining items in the tuple. When the last item is reached ab empty tuple is passed as the second parameter. This is the classic functional programming ‘head|tail` list processing idiom. An Enumerator is returned if no block is given.
177 178 179 180 181 182 183 184 185 186 187 |
# File 'lib/functional/tuple.rb', line 177 def sequence return enum_for(:sequence) unless block_given? @data.length.times do |index| last = @data.length - 1 if index == last yield(@data[index], Tuple.new) else yield(@data[index], Tuple.new(@data.slice(index+1..last))) end end end |
#to_a ⇒ Array Also known as: to_ary
Create a standard Ruby mutable array containing the tuple items in the same order.
233 234 235 |
# File 'lib/functional/tuple.rb', line 233 def to_a @data.dup end |
#union(other) ⇒ Functional::Tuple Also known as: |
Returns a new tuple by joining self with other, excluding any duplicates and preserving the order from the original tuple.
99 100 101 |
# File 'lib/functional/tuple.rb', line 99 def union(other) Tuple.new(@data | other.to_a) end |
#uniq ⇒ Functional::Tuple
Returns a new tuple by removing duplicate values in self.
138 139 140 |
# File 'lib/functional/tuple.rb', line 138 def uniq Tuple.new(@data.uniq) end |