如何在Ruby中创建用于深度复制/克隆对象的运算符?

时间:2010-07-03 10:02:16

标签: ruby operators clone deep-copy

我想通过引入一个新的运算符(例如:=

来实现以下目标
a := b = {}
b[1] = 2
p a # => {}
p b # => {1=>2}

据我了解,我需要修改Object类,但我不知道该怎么做才能得到我想要的东西。

require 'superators'
class Object
  superator ":=" operand # update, must be: superator ":=" do |operand|
    # self = Marshal.load(Marshal.dump(operand)) # ???
  end
end

你能帮我解决这个问题吗?


更新

好的,超级运动员可能不会在这里帮助我,但我还是想要这样的操作员。我怎么能(或你)为Ruby创建一个扩展,我可以将其作为模块加载?

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}

2 个答案:

答案 0 :(得分:3)

哇,superators看起来很整洁!但不幸的是,由于两个原因,这对你不起作用。首先,您的运算符与正则表达式不匹配(您不能使用冒号)。很容易,找到一个新的运营商。但是第二个我认为不可以克服,superator基本上是在左边的对象上定义的方法名称。所以你不能将它用于赋值语句。如果未定义您的变量,则无法使用它,这会引发错误。如果它是定义的,那么你不能以任何对我来说显而易见的方式改变它的类型(可能有某种程度的反射和元编程远远超出我所知道的范围,但老实说似乎不太可能......当然,我从没想过有可能创造出超级明星,所以谁知道呢。

所以我认为你又回到了破解parse.y并重建你的Ruby。

答案 1 :(得分:2)

首先,superators的语法是

superator ":=" do |operand|
  #code
end

这是一个块,因为superator是一个元编程宏。

其次,你有Marshal的东西......但它有点神奇。只要您完全了解它正在做什么,请随意使用它。

第三,你正在做的事情对于一个superator是不太可行的(我相信),因为self在一个函数中是无法修改的。 (如果有人不知道,请告诉我)

此外,在您的示例中,a必须首先存在并在能够调用其中的方法:=之前进行定义。

你最好的选择可能是:

class Object
  def deep_clone
    Marshal::load(Marshal.dump(self))
  end
end

生成对象的深层克隆。

a = (b = {}).deep_clone
b[1] = 2
p a # => {}
p b # => {1=>2}