22 votes

Fournir une valeur pour soi-même lors de l'utilisation de Proc#call

Lors de l'utilisation de Proc#call pour appeler une fonction lambda en Ruby, self se retrouve toujours avec la valeur qu'elle avait lorsque la fonction a été définie, plutôt qu'avec la valeur qu'elle a lorsque la fonction est appelée, par exemple :

$p = lambda { self }

class Dummy
  def test
    $p.call
  end
end

d = Dummy.new

> d.test
=> main

Appel test retours main alors que je voulais qu'il renvoie #<Dummy:0xf794> - une instance de Dummy qui était la valeur de self à l'endroit du code où j'ai appelé $p .

En Javascript, je passerais simplement l'objet que je veux appeler en tant que premier argument à call . Existe-t-il une telle fonctionnalité en Ruby, me permettant de définir un objet arbitraire, ou au moins la valeur actuelle de self comme nouvelle valeur de self lorsque j'appelle un Proc ?

24voto

Martin DeMello Points 4811

Vous recherchez instance_eval, qui évalue un lambda dans le contexte de l'objet appelant.

>> $p = proc { self }
=> #<Proc:0x95cece4@(irb):1 (lambda)>
>> class Dummy
>>   def test
>>     $p.call
>>   end
>> 
>>   def test1
>>     instance_eval(&$p)
>>   end
>> end

>> d = Dummy.new
=> #<Dummy:0x946f7c8>
>> d.test
=> main
>> d.test1
=> #<Dummy:0x946f7c8>

23voto

shwoodard Points 91

Vous pouvez utiliser instance_exec parce qu'il vous permet de passer des arguments au bloc, alors que instance_eval ne le permet pas.

def eval_my_proc_with_args(*args, &block)
  instance_exec(*args, &block)
end

1voto

ennuikiller Points 28005

Lambda définit une fermeture, ce qui signifie qu'elle encapsule l'environnement qu'elle avait lorsqu'elle a été définie. Si vous voulez que votre propre personne soit l'appelant, définissez simplement une méthode normale ou, mieux encore, utilisez un bloc.

0voto

Simone Carletti Points 77653

Je ne comprends pas vraiment ce que vous voulez faire, mais en Ruby vous pouvez utiliser des blocs.

class Dummy
  def test(&block)
    yield self if block_given?
    self
  end
end

d = Dummy.new
d.test
=> #<Dummy:0x7740c>

d.test do |s|
  p s
  # => #<Dummy:0x7740c>
  # you can call all Dummy methods on s
  # s.class, s...
end

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X