T
timr
Let's say I want to make a new class, Vector (that will function,
eventually, like R vectors for mathematical operations), and I write
this:
class Vector < Array
def initialize(*arr)
super(arr.flatten)
end
end
v = Vector.new(1,2,3) # => [1, 2, 3]
v.class # => Vector
v.collect{|item| item * 3}.class # => Array
v.collect!{|item| item * 3}.class # => Vector
I noticed that I inherited the Array#collect and Array#collect!
methods. Yeah for inheritance! But then look at the returned classes.
Array#collect returns and array. Array.collect! returns a Vector. If
you look at the underlying C code that defines these methods the
response makes sense. Collect! alters the object itself using the
results from the block, while collect builds a new Array from the
results of the block. But geesh, that means to have consistent
behavior, I have to add the following (and worse, look through every
other Array method to determine if the return value should be a vector
rather than an array):
class Vector < Array
def collect(&blk)
Vector.new(super) #gets the return from super and puts that
back into a vector object
end
end
v = Vector.new(1,2,3) # => [1, 2, 3]
v.class # => Vector
v.collect{|item| item * 3}.class # => Vector
v.collect!{|item| item * 3}.class # => Vector
When a method has the form of array -> an_array I want it to take a
vector -> a_vector, but I get vector -> array. Is there a simple way
to fix this for all similar methods? Or do I just have to live with
the dark side of inherited methods?
Thanks,
Tim
eventually, like R vectors for mathematical operations), and I write
this:
class Vector < Array
def initialize(*arr)
super(arr.flatten)
end
end
v = Vector.new(1,2,3) # => [1, 2, 3]
v.class # => Vector
v.collect{|item| item * 3}.class # => Array
v.collect!{|item| item * 3}.class # => Vector
I noticed that I inherited the Array#collect and Array#collect!
methods. Yeah for inheritance! But then look at the returned classes.
Array#collect returns and array. Array.collect! returns a Vector. If
you look at the underlying C code that defines these methods the
response makes sense. Collect! alters the object itself using the
results from the block, while collect builds a new Array from the
results of the block. But geesh, that means to have consistent
behavior, I have to add the following (and worse, look through every
other Array method to determine if the return value should be a vector
rather than an array):
class Vector < Array
def collect(&blk)
Vector.new(super) #gets the return from super and puts that
back into a vector object
end
end
v = Vector.new(1,2,3) # => [1, 2, 3]
v.class # => Vector
v.collect{|item| item * 3}.class # => Vector
v.collect!{|item| item * 3}.class # => Vector
When a method has the form of array -> an_array I want it to take a
vector -> a_vector, but I get vector -> array. Is there a simple way
to fix this for all similar methods? Or do I just have to live with
the dark side of inherited methods?
Thanks,
Tim