patternrubyMinor
FixedArray Class In Ruby
Viewed 0 times
fixedarrayclassruby
Problem
I had an assignment recently to build a
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:
This seems rather hacky to me though. I'm having to use metaprogramming in order to create
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
endThis 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:
-
I would extract the index checking into a method and use it in both set/get:
-
I would add
Also most style guides recommend against using
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 setAlso 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)
endContext
StackExchange Code Review Q#155792, answer score: 2
Revisions (0)
No revisions yet.