Как создать оператор для глубокого копирования / клонирования объектов в Ruby? - PullRequest
1 голос
/ 03 июля 2010

Я бы хотел добиться следующего, введя новый оператор (например, :=)

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 ]

3 голосов
/ 03 июля 2010

вау, суператоры выглядят аккуратно!Но, к сожалению, это не сработает для вас по двум причинам.Во-первых, ваш оператор не соответствует регулярному выражению (вы не можете использовать двоеточие).Достаточно просто, найти нового оператора.Но второй, который я не думаю, может быть преодолен, суператор - это, в основном, имя метода, определенное на объекте слева.Таким образом, вы не можете использовать его для операторов присваивания.Если ваша переменная не определена, вы не сможете ее использовать, что приведет к ошибке.И если он определен, то вы не можете изменить его тип каким-либо очевидным для меня способом (возможно, с некоторым уровнем отражения и метапрограммирования, выходящим далеко за пределы всего, что я знаю, но это, честно говоря, кажется маловероятным ... конечно,Я бы никогда не ожидал, что будет возможно создать суператоров, так что кто знает).

Так что я думаю, что вы вернулись к взлому parse.y и восстановлению вашего Ruby.

2 голосов
/ 03 июля 2010

Прежде всего, синтаксис для суператоров -

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

Это блок, потому что суператор - это макрос метапрограммирования.

Во-вторых, у вас что-то происходит с Marshal ... но это немного волшебства. Не стесняйтесь использовать его, если вы точно понимаете, что вы делаете.

В-третьих, то, что вы делаете, не вполне выполнимо с суператором (я полагаю), потому что 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}
...