HiveBrain v1.2.0
Get Started
← Back to all entries
patternrubyMinor

FixedArray Class In Ruby

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
fixedarrayclassruby

Problem

I had an assignment recently to build a FixedArray using Ruby. It's supposed to simulate a FixedArray in C, that is, an array that allocates a certain amount of arbitrary memory when initialized, and that this amount of memory can neither increase nor decrease. It cannot dynamically resize itself like Ruby's default Array (because at a low-enough level, there's no such thing as arrays that can resize themselves...only FixedArrays). If you try to access an index that is out of bounds, you get an exception.

Note that I cannot use Ruby's default Array (since that's kinda misses the point of the assignment, in my opinion), so you get something like this:

class OutOFBoundsException < RuntimeError
end

class FixedArray
  attr_reader :size

  def initialize(size)
    @size = size
    size.times do |index|
      self.instance_variable_set(:"@index#{index}", nil)
    end
  end

  def get(index)
    if instance_variable_defined?(:"@index#{index}")
      self.instance_variable_get("@index#{index}")
    else
      raise OutOFBoundsException
    end
  end

  def set(index, value)
    self.instance_variable_set(:"@index#{index}", value)
    value
  end

end


This seems rather hacky to me though. I'm having to use metaprogramming in order to create FixedArrays, and metaprogramming ought to be used as a last resort. Is there a better solution that can allow me to create FixedArrays?

Solution

I'm not sure that delegating to a normal array is not the best solution. Normally when I create classes like this the intent is to provide a more rigid interface over an array and delegation would be the best solution. What you have will certainly work but is going to be extremely in-efficient speed wise since those get/set/defined methods are quite slow. i.e. This is great as an exercise but I would never write code like this in a real world app.

Some changes I would make:

  • The set method does no checking so it is currently possible to add items to the array



  • Instead of instance_variable_defined? I would use (0..size).include?(index)



-
I would extract the index checking into a method and use it in both set/get:

def check_index!(index)
  raise OutOfBoundsError unless (0..size).include?(index)
end


-
I would add [] and []= aliases for get and set

Also most style guides recommend against using self. redundantly to prefix method names.

Code Snippets

def check_index!(index)
  raise OutOfBoundsError unless (0..size).include?(index)
end

Context

StackExchange Code Review Q#155792, answer score: 2

Revisions (0)

No revisions yet.