Class: Functional::Tuple

Inherits:
Synchronization::Object
  • Object
show all
Defined in:
lib/functional/tuple.rb

Overview

Note:

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.

Note:

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.

See Also:

Instance Method Summary (collapse)

Constructor Details

- (Tuple) initialize(data = [])

Create a new tuple with the given data items in the given order.

Parameters:

  • data (Array) (defaults to: [])

    the data items to insert into the new tuple

Raises:

  • (ArgumentError)

    if data is not an array or does not implement to_a



30
31
32
33
34
35
36
# File 'lib/functional/tuple.rb', line 30

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

- (Object) at(index) 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.

Parameters:

  • index (Fixnum)

    the index of the item to be retrieved

Returns:

  • (Object)

    the item at the given index or nil when index is out of bounds



45
46
47
# File 'lib/functional/tuple.rb', line 45

def at(index)
  @data[index]
end

- (Functional::Tuple) concat(other) Also known as: +

Returns a new tuple built by concatenating the two tuples together to produce a third tuple.

Parameters:

  • other (Array)

    the tuple or array-like object (responds to to_a) to operate on

Returns:



100
101
102
# File 'lib/functional/tuple.rb', line 100

def concat(other)
  Tuple.new(@data + other.to_a)
end

- (Functional::Tuple) diff(other) 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.

Parameters:

  • other (Array)

    the tuple or array-like object (responds to to_a) to operate on

Returns:



109
110
111
# File 'lib/functional/tuple.rb', line 109

def diff(other)
  Tuple.new(@data - other.to_a)
end

- (Enumerable) each {|item| ... }

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.

Yield Parameters:

  • item (Object)

    the current item

Returns:

  • (Enumerable)

    when no block is given



139
140
141
142
143
144
# File 'lib/functional/tuple.rb', line 139

def each
  return enum_for(:each) unless block_given?
  @data.each do |item|
    yield(item)
  end
end

- (Enumerable) each_with_index {|item, index| ... }

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.

Yield Parameters:

  • item (Object)

    the current item

  • index (Fixnum)

    the index of the current item

Returns:

  • (Enumerable)

    when no block is given



152
153
154
155
156
157
# File 'lib/functional/tuple.rb', line 152

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

- (Boolean) empty?

Returns true if self contains no items.

Returns:

  • (Boolean)

    true when empty else false



196
197
198
# File 'lib/functional/tuple.rb', line 196

def empty?
  @data.empty?
end

- (Boolean) eql?(other) 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.

Parameters:

  • other (Object)

    the other tuple to compare for equality

Returns:

  • (Boolean)

    true when equal else false



188
189
190
# File 'lib/functional/tuple.rb', line 188

def eql?(other)
  @data == other.to_a
end

- (Object) fetch(index, default)

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.

Parameters:

  • index (Fixnum)

    the index of the item to be retrieved

  • default (Object)

    the value to return when given an out of bounds index

Returns:

  • (Object)

    the item at the given index or default when index is out of bounds

See Also:



60
61
62
63
64
65
66
# File 'lib/functional/tuple.rb', line 60

def fetch(index, default)
  if index >= length || -index > length
    default
  else
    at(index)
  end
end

- (Object) first Also known as: head

Returns the first element of the tuple or nil when empty.

Returns:

  • (Object)

    the first element or nil



203
204
205
# File 'lib/functional/tuple.rb', line 203

def first
  @data.first
end

- (Functional::Tuple) intersect(other) 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.

Parameters:

  • other (Array)

    the tuple or array-like object (responds to to_a) to operate on

Returns:



82
83
84
# File 'lib/functional/tuple.rb', line 82

def intersect(other)
  Tuple.new(@data & other.to_a)
end

- (Fixnum) length Also known as: size

The number of items in the tuple.

Returns:

  • (Fixnum)

    the number of items in the tuple



71
72
73
# File 'lib/functional/tuple.rb', line 71

def length
  @data.length
end

- (Functional::Tuple) repeat(multiple) 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.

Parameters:

  • multiple (Fixnum)

    the number of times to concatenate self

Returns:

Raises:

  • (ArgumentError)

    when multiple is a negative number



120
121
122
123
124
# File 'lib/functional/tuple.rb', line 120

def repeat(multiple)
  multiple = multiple.to_i
  raise ArgumentError.new('negative argument') if multiple < 0
  Tuple.new(@data * multiple)
end

- (Functional::Tuple) rest 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.

Returns:



212
213
214
215
216
217
218
# File 'lib/functional/tuple.rb', line 212

def rest
  if @data.length <= 1
    Tuple.new
  else
    Tuple.new(@data.slice(1..@data.length-1))
  end
end

- (Enumerable) sequence {|head, tail| ... }

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.

Yield Parameters:

  • head (Object)

    the current item for this iteration

  • tail (Tuple)

    the remaining items (tail) or an empty tuple when processing the last item

Returns:

  • (Enumerable)

    when no block is given



169
170
171
172
173
174
175
176
177
178
179
# File 'lib/functional/tuple.rb', line 169

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

- (Array) to_a Also known as: to_ary

Create a standard Ruby mutable array containing the tuple items in the same order.

Returns:

  • (Array)

    the new array created from the tuple



225
226
227
# File 'lib/functional/tuple.rb', line 225

def to_a
  @data.dup
end

- (Functional::Tuple) union(other) Also known as: |

Returns a new tuple by joining self with other, excluding any duplicates and preserving the order from the original tuple.

Parameters:

  • other (Array)

    the tuple or array-like object (responds to to_a) to operate on

Returns:



91
92
93
# File 'lib/functional/tuple.rb', line 91

def union(other)
  Tuple.new(@data | other.to_a)
end

- (Functional::Tuple) uniq

Returns a new tuple by removing duplicate values in self.

Returns:



130
131
132
# File 'lib/functional/tuple.rb', line 130

def uniq
  Tuple.new(@data.uniq)
end