Question

J'ai récemment essayé de faire quelque chose du genre:

a = "some string"
b = Proc.new{ upcase }
a.instance_eval b

Ce qui donne l'erreur:

TypeError: impossible de convertir Proc en String

mais cela fonctionne:

def b(&block)
  "some string".instance_eval &block
end

b{ upcase }

Un autre regard avec cette méthode:

def b(&block)
  "some string".instance_eval block
end

Renvoie la même erreur de Proc to String.

Donc ... ma compréhension des blocs est qu'ils ne sont que des processus.Mais il y a évidemment quelque chose de spécial à avoir cette esperluette & ...

Quelqu'un peut-il m'expliquer cela?Est-il possible de convertir un processus normal en tout ce qui est spécial à propos de cet objet &block?

modifier

Je viens de comprendre ma deuxième question, ajoutez un & au processus ... c'était facile, mais qu'est-ce que cela fait vraiment?

Était-ce utile?

La solution

Tout ce que vous avez à faire pour que votre premier exemple fonctionne est le suivant:

>> a.instance_eval &b #=> "SOME STRING"

La raison en est que instance_eval a besoin d'une chaîne ou d'un bloc et l'esperluette fournit ce dernier.

Pour comprendre les différences entre les blocs et les processus, le billet de blog suivant peut peut-être vous aider:

Comprendre les blocs Ruby, les processuset Lambdas

Autres conseils

La différence est que a.instance_eval b passe b comme argument normal à instance_eval, alors que a.instance_eval &b le passe comme un bloc.Ce sont deux choses différentes.

Considérez cet appel de méthode:

obj.foo(bar) do |x| 
  stuff(x) 
end

Cela invoque la méthode foo avec un argument normal (bar) et un argument de bloc (do |x| stuff(x) end).Dans la définition de la méthode, ils se distinguent en préfixant & au paramètre de bloc:

def foo(arg, &block)

Et si vous souhaitez passer une expression variable au lieu d'un bloc littéral, cela est également accompli en préfixant & à l'expression (qui devrait donner un Proc).

Si vous passez un argument sans &, il va dans l'emplacement arg au lieu de l'emplacement block .Peu importe que l'argument soit une instance de Proc.La syntaxe dicte comment elle est transmise et traitée par la méthode.

C'est parce que instance_eval accepte une chaîne à eval ou un bloc.instance_eval(&block) passe votre block en tant que bloc à instance_eval.

La différence cruciale est que une instance Proc est un objet tandis que un bloc n'est pas un objet .Le & est un opérateur qui interchange un bloc et une instance Proc mutuellement.

Tous les arguments d'une méthode doivent être un objet.En plus des arguments, une méthode peut prendre un bloc.instance_eval est une méthode qui prend soit un argument String, soit un bloc.Passer un objet Proc ne satisfera aucun des cas.Si vous attachez & à un objet Proc, il sera géré comme un bloc.

Cela fonctionnera:

a = "some string"
b = Proc.new{ upcase }
a.instance_eval &b

La méthode instance_eval peut recevoir un bloc d'arguments. b est un Proc.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top