On 5/1/05, Eric Mahurin <eric_mahurin / yahoo.com> wrote:
> Anybody know of any collection (i.e. Array/Hash) classes where
> the keys and/or values can be assigned a fixed class?  And for
> classes that have variable length objects the length be also
> potentially fixed across the collection?  The main purpose of
> doing this would be memory usage.  You wouldn't have to store
> the class (and possibly object length and pointer to allocated
> space) per element and instead just have the raw data in the
> collection.  You would be able to get the same memory
> utilization as C per element if done right.
> 
> Here would be a few examples of what I'm talking about and how
> much space per element it would take:
> 
> - array of Floats (64 bits per element)
> - array of N-bit integers (N bits per element)
> - hash of 2-character strings (2*8 bits per key and Object per
> value)
> - array of array of 8 Floats (8*64 bits per line)
> 
> For dealing with large data structures, this could be
> invaluable for memory usage.

You are looking for the String class, which can contain any data you
want. Here's a quick example:

class FloatArray         
  def initialize(size=0, filler=0.0)        
    @values = ""
    if block_given?
      size.times do |n|
        self << yield(n)
      end
    else
      size.times do
        self << filler
      end
    end
  end
  
  def <<(item)
    @values << [item].pack('F')
    self
  end
  
  def [](idx, size=nil)
    if size
      a = FloatArray.new
      val = @values[idx.to_int*4, size*4]
      a.instance_eval{@values = val}
    elsif idx.kind_of? Range
      a = FloatArray.new
      val = @values[idx.min.to_int*4...idx.max.to_i*4]
      a.instance_eval{@values = val}
    else
      @values[idx.to_int*4,4].unpack('F').first
    end
  end
  
  def inspect
    self.class.inspect + @values.unpack('F*').inspect
  end
end

...add a definition for #slice! and one for #insert and you've got
most of the work done making this transparently Arrayish.

cheers,
Mark