Class: Tuple

Inherits:
Object show all
Includes:
Comparable, Enumerable, Multiton
Defined in:
lib/standard/facets/tuple.rb

Overview

Tuple

Tuple is essentially an Array, but Comaparable and Immutable.

A tuple can be made using #new or #[] just as one builds an array, or using the #to_t method on a string or array. With a string tuple remembers the first non-alphanumeric character as the tuple divider.

Usage

t1 = Tuple[1,2,3]
t2 = Tuple[2,3,4]

(t1 < t2)   #=> true
(t1 > t2)   #=> false

t1 = '1.2.3'.to_t
t2 = '1-2-3'.to_t

t1.to_s  #=> "1.2.3"
t2.to_s  #=> "1.2.3"

(t1 == t2)  #=> true

Keep in mind that Tuple is not the same as Tuple.

– TODO: The #hash method needs a touch-up.

TODO: There are a few more methods yet to borrow from Array. Consider how #+, #-, etc. ought to work. ++

Constant Summary collapse

SEGMENT_SEPARATOR =
'.'

Constants included from Enumerable

Enumerable::Arguments

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Comparable

#at_least, #at_most, #clip, #cmp

Methods included from Enumerable

#accumulate, #accumulate_all, #apply, #cluster, #compact_map, #defer, #each_by, #every, #every!, #ewise, #exclude?, #expand, #filter, #find_yield, #frequency, #graph, #hashify, #hinge, #incase?, #key_by, #map_by, #map_send, #map_to, #map_with, #map_with_index, #mash, #modulate, #occur, #only, #only?, #organize_by, #pair, #per, #purge, #recursively, #squeeze, #sum, #threaded_map, #threaded_map_send, #unassociate, #uniq_by, #value_by, #visit, #with_position

Methods included from Multiton

#_dump, #clone, #dup

Methods included from Multiton::Inclusive

#included

Constructor Details

#initialize(arg = 0, default = 0, &blk) ⇒ Tuple

Returns a new instance of Tuple.



53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/standard/facets/tuple.rb', line 53

def initialize(arg=0, default=0, &blk)
  if block_given?
    @values = []
    arg.times { |i| @values << blk[i] }
  elsif Integer === arg
    @values = [ default ] * arg
  else
    @values = arg.to_ary
  end
  @default = default
  ##@divider = '.'
end

Instance Attribute Details

#defaultObject

Returns the value of attribute default.



66
67
68
# File 'lib/standard/facets/tuple.rb', line 66

def default
  @default
end

Class Method Details

.[](*args) ⇒ Object



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

def []( *args )
  instance( args )
end

.cast_from_array(arr) ⇒ Object



217
218
219
# File 'lib/standard/facets/tuple.rb', line 217

def cast_from_array( arr )
  self.instance( arr )
end

.cast_from_string(str, &yld) ⇒ Object

Translates a string in the form on a set of numerical and/or alphanumerical characters separated by non-word characters (eg W+) into a Tuple. The values of the tuple will be converted to integers if they are purely numerical.

Tuple.cast_from_string('1.2.3a')  #=> [1,2,"3a"]

It you would like to control the interpretation of each value as it is added to the tuple you can supply a block.

Tuple.cast_from_string('1.2.3a'){ |v| v.upcase }  #=> ["1","2","3A"]

This method is called by String#to_t.



205
206
207
208
209
210
211
212
213
214
# File 'lib/standard/facets/tuple.rb', line 205

def cast_from_string( str, &yld )
  args = str.to_s.split(/\W+/)
  div = /\W+/.match( str.to_s )[0]
  if block_given?
    args = args.collect{ |a| yld[a] }
  else
    args = args.collect { |i| /^[0-9]+$/ =~ i ? i.to_i : i }
  end
  self.instance(args) #.divider( div )
end

.constraint_to_lambda(constraint, &yld) ⇒ Object

Parses a constraint returning the operation as a lambda.



222
223
224
225
# File 'lib/standard/facets/tuple.rb', line 222

def constraint_to_lambda( constraint, &yld )
  op, val = *parse_constraint( constraint, &yld )
  lambda { |t| t.send(op, val) }
end

.multiton_id(arg = 0, default = 0, &block) ⇒ Object



41
42
43
44
45
46
47
48
49
50
51
# File 'lib/standard/facets/tuple.rb', line 41

def self.multiton_id(arg=0, default=0, &block)
  if block_given?
    values = []
    arg.times { |i| values << block[i] }
  elsif Integer === arg
    values = [ default ] * arg
  else
    values = arg.to_ary
  end
  values
end

.parse_constraint(constraint, &yld) ⇒ Object



228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
# File 'lib/standard/facets/tuple.rb', line 228

def parse_constraint( constraint, &yld )
  constraint = constraint.strip
  re = %r{^(=~|~>|<=|>=|==|=|<|>)?\s*(\d+(:?[-.]\d+)*)$}
  if md = re.match( constraint )
    if op = md[1]
      op = '=~' if op == '~>'
      op = '==' if op == '='
      val = cast_from_string( md[2], &yld ) #instance( md[2] )
    else
      op = '=='
      val = cast_from_string( constraint, &yld ) #instance( constraint )
    end
  else
    raise ArgumentError, "invalid constraint"
  end
  return op, val
end

Instance Method Details

#<<(obj) ⇒ Object

Unlike Array, Tuple#<< cannot act in place becuase Tuple’s are immutable.



124
125
126
# File 'lib/standard/facets/tuple.rb', line 124

def <<( obj )
  self.class.instance( to_a << obj )
end

#<=>(other) ⇒ Object



151
152
153
154
155
156
157
158
# File 'lib/standard/facets/tuple.rb', line 151

def <=>( other )
  other = other.to_t
  [size, other.size].max.times do |i|
    c = self[i] <=> other[i]
    return c if c != 0
  end
  0
end

#=~(other) ⇒ Object

For pessimistic constraint (like ‘~>’ in gems)



161
162
163
164
165
166
# File 'lib/standard/facets/tuple.rb', line 161

def =~( other )
  other = other.to_t
  upver = other.dup
  upver[0] += 1
  self >= other and self < upver
end

#[](i) ⇒ Object



111
112
113
# File 'lib/standard/facets/tuple.rb', line 111

def [](i)
  @values.fetch(i,@default)
end

#[]=(i, v) ⇒ Object



115
116
117
# File 'lib/standard/facets/tuple.rb', line 115

def []=(i,v)
  @values[i] = v
end

#each(&block) ⇒ Object



103
104
105
# File 'lib/standard/facets/tuple.rb', line 103

def each( &block )
  @values.each( &block )
end

#each_index(&block) ⇒ Object



107
108
109
# File 'lib/standard/facets/tuple.rb', line 107

def each_index( &block )
  @values.each_index( &block )
end

#empty?Boolean

Returns:

  • (Boolean)


97
98
99
100
101
# File 'lib/standard/facets/tuple.rb', line 97

def empty?()
  return true if @values.empty?
  return true if @values == [ @default ] * @values.size
  false
end

#eql?(other) ⇒ Boolean

Returns true if two tuple references are for the very same tuple.

Returns:

  • (Boolean)


145
146
147
148
# File 'lib/standard/facets/tuple.rb', line 145

def eql?( other )
  return true if object_id == other.object_id
  ##return true if values.eql? other.values
end

#firstObject



168
# File 'lib/standard/facets/tuple.rb', line 168

def first() @values.first end

#hashObject

Unique hash value.



177
178
179
180
181
# File 'lib/standard/facets/tuple.rb', line 177

def hash
  # TODO: This needs to take into account the default
  # and maybe the divider too.
  to_a.hash
end

#indexObject



119
# File 'lib/standard/facets/tuple.rb', line 119

def index()  @values.index end

#inspectObject



82
# File 'lib/standard/facets/tuple.rb', line 82

def inspect() to_a.inspect end

#lastObject



169
# File 'lib/standard/facets/tuple.rb', line 169

def last()  @values.last end

#lengthObject



95
# File 'lib/standard/facets/tuple.rb', line 95

def length() @values.size end

#majorObject

These are useful for using a Tuple as a version.



172
# File 'lib/standard/facets/tuple.rb', line 172

def major() @values.first end

#minorObject



173
# File 'lib/standard/facets/tuple.rb', line 173

def minor() @values.at(1) end

#popObject



128
# File 'lib/standard/facets/tuple.rb', line 128

def pop() Tuple.instance( to_a.pop ) end

#pot(obj) ⇒ Object Also known as: unshift

Stands for “Put On Top”. This method is the opposite of #pull and is otherwise known as #unshift.



138
# File 'lib/standard/facets/tuple.rb', line 138

def pot( obj ) Tuple.instance( to_a.unshift(obj) ) end

#pullObject Also known as: shift

Pulls a value off the beginning of a tuple. This method is otherwsie known as #shift.



134
# File 'lib/standard/facets/tuple.rb', line 134

def pull() Tuple.instance( to_a.shift ) end

#push(obj) ⇒ Object



130
# File 'lib/standard/facets/tuple.rb', line 130

def push( obj ) Tuple.instance( to_a.push(obj) ) end

#rindexObject



120
# File 'lib/standard/facets/tuple.rb', line 120

def rindex() @values.rindex end

#sizeObject



94
# File 'lib/standard/facets/tuple.rb', line 94

def size()   @values.size end

#teenyObject



174
# File 'lib/standard/facets/tuple.rb', line 174

def teeny() @values.at(2) end

#to_aObject



87
# File 'lib/standard/facets/tuple.rb', line 87

def to_a()   Array(@values) end

#to_aryObject



88
# File 'lib/standard/facets/tuple.rb', line 88

def to_ary() Array(@values) end

#to_s(divider = nil) ⇒ Object



90
91
92
# File 'lib/standard/facets/tuple.rb', line 90

def to_s(divider=nil)
  @values.join(divider || SEGMENT_SEPARATOR)
end

#to_tObject



84
# File 'lib/standard/facets/tuple.rb', line 84

def to_t()     self end

#to_tupleObject



85
# File 'lib/standard/facets/tuple.rb', line 85

def to_tuple() self end

#valuesObject (protected)



76
# File 'lib/standard/facets/tuple.rb', line 76

def values() @values end