2010-11-28 4 views
8

Existe-t-il un moyen simple dans Ruby de produire une copie d'un Proc? J'ai un Proc appelé @foo. Je veux une autre méthode pour augmenter périodiquement @foo avec une logique supplémentaire. Par exemple:Comment copier en profondeur une proc dans Ruby?

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

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

Je ne suis pas veulent la deuxième ligne qui fait l'augmentation pour produire une fonction récursive. Au lieu de cela, je veux @foo à être lié par la valeur dans le champ lexical de la nouvelle définition de @foo, produisant une fonction qui ressemble plus à ceci:

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

je reçois une récursion infinie et un débordement de pile éventuelle à la place, en raison de la fonction résultante qui ressemble à ceci:

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

Je voudrais que le code comme ceci:

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

mais clone ne fonctionne pas sur procs. En outre, le hack de copie en profondeur standard de Ruby, utilisant marshal et unmarshal, ne fonctionne pas non plus sur Procs. Y a-t-il un moyen de le faire?

Répondre

7

Même si clone travaillerait sur Proc s, il ne vous aidera pas, parce que vous seriez encore appellerez clone sur la nouvelle valeur de @foo, pas sur le précédent comme vous voulez. Vous pouvez simplement stocker l'ancienne valeur @foo dans une variable locale que le lambda peut fermer.

Exemple:

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

De cette façon old_foo fera référence à la valeur que @foo avait quand augment_foo est appelé et tout fonctionnera comme vous voulez.

Questions connexes