Как мне глубоко скопировать Proc в Ruby? - PullRequest
8 голосов
/ 28 ноября 2010

Есть ли в Ruby простой способ создания копии Proc?

У меня есть проц, который называется @foo. Я хочу, чтобы другой метод периодически дополнял @foo дополнительной логикой. Например:

# create initial Proc
@foo = lambda { |x| x }

# augment with more logic
@foo = lambda { |x| x > 1 ? x*x : @foo[x] }

Я не хочу, чтобы вторая строка, которая выполняет увеличение, производила рекурсивную функцию. Вместо этого я хочу, чтобы значение @foo было связано со значением в лексической области нового определения @foo, создавая функцию, которая выглядит примерно так:

@foo = lambda { |x| x > 1 ? x*x : lambda{ |x| x }[x] }

Вместо этого я получаю бесконечную рекурсию и возможное переполнение стека, потому что получающаяся функция выглядит следующим образом:

@foo = lambda { |x| x > 1 ? x*x : lambda { |x| x > 1 ? x*x : { lambda |x| # etc...

Я бы хотел, чтобы код был таким:

# augment with more logic
@foo = lambda { |x| x > 1 ? x*x : (@foo.clone)[x] }

но клон не работает на Procs.

Кроме того, стандартный хак глубокого копирования Ruby, использующий маршал и демаршал, также не работает на Procs. Есть ли способ сделать это?

1 Ответ

7 голосов
/ 28 ноября 2010

Даже если clone будет работать на Proc с, это не поможет вам, потому что вы все равно будете звонить clone с новым значением @foo, а не с предыдущим, как вы хотите.

Вместо этого вы можете просто сохранить старое значение @foo в локальной переменной, которую может закрывать лямбда.

Пример:

def augment_foo()
  old_foo = @foo
  @foo = lambda { |x| x > 1 ? x*x : old_foo[x] }
end

Таким образом, old_foo будет ссылаться на значение, которое @foo имело при вызове augment_foo, и все будет работать так, как вы хотите.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...