I’m trying to subclass Array in ruby to make it randomize its elements when flatten! is called. Looking at the source code for Array#flatten (http://ruby-doc.org/core/classes/Array.src/M002218.html), it looks like it should recursively call flatten! on any array contained within an array. So, I tried doing something like this:
class RandArray < Array
def randomize!
self.sort!{rand(3)-1}
end
def flatten!
randomize!
super
end
end
However, when a normal array contains my RandArray and flatten is called on the normal array, flatten! is never called in my array. I figure ruby is just calling some other method to flatten the arrays recursively, but I can’t figure out what that is. Any tips?
I am not an absolute expert on this but Ruby’s Array is written as C code. here is the code for flatten! :
As you can see on this line,
and here is the implementation for this flatten C function :
The flatten! code calls directly the C flatten function for any element of the array that validates rb_check_array_type it doesn’t go back to the ruby code.Instead it accesses the underlying C structure directly bypassing your overloaded implementation.
Not sure how to override this, I think one way could be to reopen Array and rewrite the flatten and flatten! function as pure ruby.
You would take a performance hit, but then you would be able to overload it as you see fit. And you could always use aliasing to have a “flatten_native” and a “flatten_native!” function on your modified array, to get the perfs back on some cases.