D
David Brady
Hello,
I'm writing some code that benefits from extending Array. One of the
methods wants to be a bang method. How do I reassign the contents of an
Array from within it? (I recognize that subclassing Array might be more
proper, but I think the problem exists in the subclass as well.)
class Array
# returns copy of array, with each value divided by the sum of
# the array elements. e.g. [1,2,2] => [0.2, 0.4, 0.4].
# (this code works fine)
def normalize
total = Float( self.inject {|x,y| x+y} )
self.collect {|x| x/total}
end
# returns modified array unless array.sum == 1.0, in which case
# array is not modified and method returns nil
# (this code does not work: syntax error - cannot assign to self)
def normalize!
total = Float( self.inject {|x,y| x+y} )
if total.zero?
nil
else
self = self.collect {|x| x/total}
end
end
end
I can work around the problem by iterating and using self.[]= but the
collect is so much cleaner, I have to wonder if there's not a way to use it.
Hrm, I've just found "Array#collect!", which will do the trick I need,
but I still wonder what the proper Ruby idiom is for extending a class
with a bang method that essentially modifies or replaces the entire
contents of the object, when there isn't an accessor method. For
example, how would you do "Fixnum#div!(x)", e.g. the equivalend of f /= x?
I recognize that this entire line of reasoning may be the result of
wrongheaded thinking about Ruby. If so, please enlighten me.
-dB
I'm writing some code that benefits from extending Array. One of the
methods wants to be a bang method. How do I reassign the contents of an
Array from within it? (I recognize that subclassing Array might be more
proper, but I think the problem exists in the subclass as well.)
class Array
# returns copy of array, with each value divided by the sum of
# the array elements. e.g. [1,2,2] => [0.2, 0.4, 0.4].
# (this code works fine)
def normalize
total = Float( self.inject {|x,y| x+y} )
self.collect {|x| x/total}
end
# returns modified array unless array.sum == 1.0, in which case
# array is not modified and method returns nil
# (this code does not work: syntax error - cannot assign to self)
def normalize!
total = Float( self.inject {|x,y| x+y} )
if total.zero?
nil
else
self = self.collect {|x| x/total}
end
end
end
I can work around the problem by iterating and using self.[]= but the
collect is so much cleaner, I have to wonder if there's not a way to use it.
Hrm, I've just found "Array#collect!", which will do the trick I need,
but I still wonder what the proper Ruby idiom is for extending a class
with a bang method that essentially modifies or replaces the entire
contents of the object, when there isn't an accessor method. For
example, how would you do "Fixnum#div!(x)", e.g. the equivalend of f /= x?
I recognize that this entire line of reasoning may be the result of
wrongheaded thinking about Ruby. If so, please enlighten me.
-dB