1

Je n'arrive pas à comprendre quand utiliser l'esperluette pour transmettre des symboles à des fonctions représentant une méthode. Par exemple, si je voulais calculer la somme de la gamme 1..10, je pouvais faire ce qui suit:Différence entre passing &: méthode et: méthode comme arguments de fonction dans ruby ​​

(1..10).inject(:+)

Cela me conduit à l'origine de croire que si vous vouliez passer un symbole pour définir un Si vous utilisez la méthode "Magiquement" dans la fonction, vous devez passer le nom de la fonction comme symbole. Mais je vois quelque chose comme ça dans des rails:

total = Product.find(product_list).sum(&:price)

Si je comprends bien, &: prix est le même que l'appel: price.to_proc. Je ne comprends pas comment cela fonctionne.

+0

Cela n'a rien à voir avec Enumerable # Inject, je l'ai juste utilisé comme exemple. – Senjai

+0

L'effet de ': +' dépend fortement de 'injecter' dans votre exemple alors que' &: price' ne le fait pas. –

+0

Merci d'avoir éclairci ça pour moi. – Senjai

Répondre

4

Dans la liste des paramètres réels d'un appel de méthode, &object est intégré dans la syntaxe, qui sera

  1. convertir object à un Proc utilisant object.to_proc
  2. passe le Proc comme paramètre de bloc du procédé

Symbol#to_proc convertit le symbole (par exemple: the_symbol) en proc {|obj| obj.send(:the_symbol)}. Et vous pouvez utiliser cette syntaxe chaque fois que object répond à la méthode to_proc et renvoie un Proc.

abc = "aha~" 
class << abc 
    def to_proc 
    proc {|obj| obj.to_i * 2 } 
    end 
end 
p ["1", "2", "3"].map(&abc) 
#=> [2, 4, 6] 

(1..10).inject(:+) montre que injectent accepte un symbole en tant que paramètre. La façon dont le symbole est utilisé est un comportement spécifique à la méthode. Dans le cas particulier de inject, cela a le même effet que (1..10).inject{|a, b| a.send(:+, b)}. C'est juste un paramètre simple, normal, l'effet dépend de l'implémentation de la méthode qui accepte le symbole comme paramètre.

Notez que sum dans ActiveSupport accepte un bloc avec un seul paramètre, ce qui a pour effet « valeurs de carte dans la séquence d'origine à de nouvelles et de calculer la somme d'entre eux », donc

total = Product.find(product_list).sum(&:price) 

est équivalent comme

total = Product.find(product_list).sum(&proc{|p| p.send(:price)}) 
# or you may write 
total = Product.find(product_list).sum{|p| p.price } 

qui a la même valeur de retour comme ce qui suit, mais ne produira pas de tableau de température intermédiaire:

total = Product.find(product_list).map{|p| p.price}.sum 
+0

Je pensais et est un raccourci pour to_proc, pas to_sym, ai-je tort? – Senjai

+0

Comment fonctionne: price.to_proc interagir avec la somme? Je veux dire, je suppose que cela est en quelque sorte converti en produit.prix, et résume ces prix. – Senjai

+0

@Senjai une faute de frappe, mise à jour. –

Questions connexes