Ruby - 子类化数组以使其在展平时随机化
我正在尝试在 ruby 中对 Array 进行子类化,以使其在展平时随机化其元素!被称为。查看 Array#flatten 的源代码 (http://ruby- doc.org/core/classes/Array.src/M002218.html),看起来应该递归调用展平!在数组中包含的任何数组上。所以,我尝试做这样的事情:
class RandArray < Array
def randomize!
self.sort!{rand(3)-1}
end
def flatten!
randomize!
super
end
end
但是,当普通数组包含我的 RandArray 并在普通数组上调用 flatten 时,请展平!我的数组中从未被调用过。我认为 ruby 只是调用其他一些方法来递归地展平数组,但我不知道那是什么。有什么建议吗?
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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我不是这方面的绝对专家,但 Ruby 的数组是用 C 代码编写的。这是展平的代码! :
正如您在这一行中看到的,
这里是此扁平化 C 函数的实现:
扁平化!代码直接调用验证 rb_check_array_type 的数组中任何元素的 C 平展函数,它不会返回到 ruby 代码。相反,它会直接绕过重载实现来访问底层 C 结构。
不知道如何覆盖这个,我认为一种方法可能是重新打开数组并重写展平和展平!功能与纯红宝石相同。
您可能会受到性能影响,但随后您可以根据需要超载它。并且您始终可以使用别名来获得“flatten_native”和“flatten_native!”在修改后的数组上运行函数,以在某些情况下恢复性能。
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.
Jean 是正确的,flatten 在幕后调用 C 函数。您可以修补 Array 类并覆盖默认的展平!方法,同时仍然保留对原始方法的访问。
或者你可以添加一个 flatten_with_randomize !到 Array 类并使用它来代替并保持原始扁平化!方法完好无损。
Jean is correct, flatten calls a C function behind the scenes. You could patch the Array class and override the default flatten! method, while still retaining access to the original method.
Or you could just add a flatten_with_randomize! to the Array class and use that instead and keep the original flatten! method intact.