How to create an operator for deep copy/cloning of objects in Ruby?
I would like to achieve the following by introducing a new operator (e.g. :开发者_StackOverflow中文版=
)
a := b = {}
b[1] = 2
p a # => {}
p b # => {1=>2}
As far as I understand, I need to modify the Object
class, but I don't know what to do in order to get what I want.
require 'superators'
class Object
superator ":=" operand # update, must be: superator ":=" do |operand|
# self = Marshal.load(Marshal.dump(operand)) # ???
end
end
Could you help me with this?
Update
Ok, superators will probably not help me here, but I still want such operator. How can I (or you) create an extension for Ruby, which I could load as a module?
require 'deep_copy_operator'
a !?= b = {} # I would prefer ":=" but don't really care how it is spelled
b[1] = 2
p a # => {}
p b # => {1=>2}
wow, superators look neat! But unfortunately, this won't work for you, for two reasons. First, your operator does not match the regex (you cannot use a colon). Easy enough, find a new operator. But the second one I don't think can be overcome, the superator is basically a method name defined on the object to the left. So you can't use it for assignment statements. If your variable is not defined, then you cannot use it, that would raise an error. And if it is defined, then you can't change its type in any way that is obvious to me (maybe with some level of reflection and metaprogramming that is way beyond anything I know, but it honestly seems unlikely... of course, I would have never expected it to be possible to create superators, so who knows).
So I think you're back to hacking parse.y and rebuilding your Ruby.
First of all, the syntax for superators is
superator ":=" do |operand|
#code
end
It's a block, because superator is a metaprogramming macro.
Secondly, you have something going their with Marshal
...but it's a bit of magic-ish. Feel free to use it as long as you understand exactly what it is you're doing.
Thirdly, what you are doing isn't quite doable with a superator (I believe), because self
cannot be modified during a function. (if someone knows otherwise, please let me know)
Also, in your example, a
must first exist and be defined before being able to call the method :=
in it.
Your best bet is probably:
class Object
def deep_clone
Marshal::load(Marshal.dump(self))
end
end
to generate a deep clone of an object.
a = (b = {}).deep_clone
b[1] = 2
p a # => {}
p b # => {1=>2}
精彩评论