J'ai trouvé ce code dans un RailsCast :
def tag_names
@tag_names || tags.map(&:name).join(' ')
end
Que signifie l' (&:name)
in map(&:name)
?
ruby
syntax
operators
parameter-passing
collimarco
la source
la source
Réponses:
C'est un raccourci pour
tags.map(&:name.to_proc).join(' ')
Si
foo
est un objet avec uneto_proc
méthode, vous pouvez le passer à une méthode as&foo
, qui l'appellerafoo.to_proc
et l'utilisera comme bloc de la méthode.La
Symbol#to_proc
méthode a été initialement ajoutée par ActiveSupport mais a été intégrée à Ruby 1.8.7. Voici sa mise en œuvre:la source
&
, c'esttags.map(&:name.to_proc).join(' ')
Un autre raccourci cool, inconnu de beaucoup, est
qui est un raccourci pour
En appelant,
method(:foo)
nous avons pris unMethod
objetself
qui représente safoo
méthode, et avons utilisé le&
pour signifier qu'il a uneto_proc
méthode qui le convertit en aProc
.C'est très utile lorsque vous voulez faire des choses sans style. Un exemple consiste à vérifier s'il existe une chaîne dans un tableau qui est égale à la chaîne
"foo"
. Il y a la voie conventionnelle:Et il y a la manière sans point:
La manière préférée devrait être la plus lisible.
la source
array.each{|e| foo(e)}
est encore plus court :-) +1 quand même&method
?[1,2,3].map(&Array.method(:new))
C'est équivalent à
la source
Notons également que la
#to_proc
magie de l' esperluette peut fonctionner avec n'importe quelle classe, pas seulement avec Symbol. De nombreux Rubyistes choisissent de définir#to_proc
sur la classe Array:Esperluette
&
fonctionne en envoyant unto_proc
message sur son opérande, qui, dans le code ci-dessus, est de classe Array. Et puisque j'ai défini la#to_proc
méthode sur Array, la ligne devient:la source
C'est un raccourci pour
tags.map { |tag| tag.name }.join(' ')
la source
&
opérateur unaire fait appelto_proc
à son opérande. Elle n'est donc pas spécifique à la méthode map et fonctionne en fait sur toute méthode qui prend un bloc et transmet un ou plusieurs arguments au bloc.est le même que
&:name
utilise simplement le symbole comme nom de méthode à appeler.la source
La réponse de Josh Lee est presque correcte, sauf que le code Ruby équivalent aurait dû être le suivant.
ne pas
Avec ce code, lorsqu'il
print [[1,'a'],[2,'b'],[3,'c']].map(&:first)
est exécuté, Ruby divise la première entrée[1,'a']
en 1 et «a» pour donnerobj
1 etargs*
«a» pour provoquer une erreur car l'objet Fixnum 1 n'a pas la méthode self (qui est: la première).Quand
[[1,'a'],[2,'b'],[3,'c']].map(&:first)
est exécuté;:first
est un objet Symbol, donc quand&:first
est donné à une méthode de carte en tant que paramètre, Symbol # to_proc est invoqué.la carte envoie un message d'appel à: first.to_proc avec le paramètre
[1,'a']
, par exemple,:first.to_proc.call([1,'a'])
est exécuté.La procédure to_proc dans la classe Symbol envoie un message d'envoi à un objet tableau (
[1,'a']
) avec le paramètre (: first), par exemple,[1,'a'].send(:first)
est exécuté.itère sur le reste des éléments de l'
[[1,'a'],[2,'b'],[3,'c']]
objet.Cela revient à exécuter l'
[[1,'a'],[2,'b'],[3,'c']].map(|e| e.first)
expression.la source
[1,2,3,4,5,6].inject(&:+)
- inject attend un lambda avec deux paramètres (mémo et item) et le:+.to_proc
livre -Proc.new |obj, *args| { obj.send(self, *args) }
ou{ |m, o| m.+(o) }
Il se passe deux choses ici, et il est important de comprendre les deux.
Comme décrit dans d'autres réponses, la
Symbol#to_proc
méthode est appelée.Mais la raison
to_proc
pour laquelle le symbole est appelé est qu'il est passé enmap
tant qu'argument de bloc. Placer&
devant un argument dans un appel de méthode le fait passer de cette façon. Cela est vrai pour toute méthode Ruby, pas seulementmap
pour les symboles.Le
Symbol
est converti en unProc
car il est transmis en tant que bloc. Nous pouvons le montrer en essayant de passer un proc à.map
sans esperluette:Même s'il n'a pas besoin d'être converti, la méthode ne saura pas comment l'utiliser car elle attend un argument de bloc. Le passer avec
&
donne.map
le bloc qu'il attend.la source
(&: nom) est l'abréviation de (&: nom.à_proc) c'est la même chose que
tags.map{ |t| t.name }.join(' ')
to_proc est en fait implémenté en C
la source
carte (&: nom) prend un objet énumérable (balises dans votre cas) et exécute la méthode de nom pour chaque élément / balise, produisant chaque valeur renvoyée par la méthode.
C'est un raccourci pour
qui retourne le tableau des noms d'élément (tag)
la source
Il exécute essentiellement l'appel de méthode
tag.name
sur chaque balise du tableau.Il s'agit d'un raccourci rubis simplifié.
la source
Bien que nous ayons déjà d'excellentes réponses, en regardant dans la perspective d'un débutant, j'aimerais ajouter des informations supplémentaires:
Cela signifie que vous transmettez une autre méthode en tant que paramètre à la fonction de carte. (En réalité, vous passez un symbole qui est converti en proc. Mais ce n'est pas si important dans ce cas particulier).
Ce qui est important, c'est que vous ayez un
method
nomname
qui sera utilisé par la méthode map comme argument au lieu dublock
style traditionnel .la source
Tout d'abord,
&:name
est un raccourci pour&:name.to_proc
, où:name.to_proc
renvoie unProc
(quelque chose de similaire, mais pas identique à un lambda) qui, lorsqu'il est appelé avec un objet comme (premier) argument, appelle laname
méthode sur cet objet.Deuxièmement, alors que
&
indef foo(&block) ... end
convertit un bloc passé enfoo
aProc
, il fait le contraire lorsqu'il est appliqué à aProc
.Ainsi,
&:name.to_proc
est un bloc qui prend un objet comme argument et appelle laname
méthode dessus, c'est-à-dire{ |o| o.name }
.la source
Voici
:name
le symbole qui pointe vers la méthodename
de l'objet tag. Lorsque nous passons&:name
àmap
, il sera traiténame
comme un objet proc. Pour faire court,tags.map(&:name)
agit comme:la source
ça veut dire
la source
C'est la même chose que ci-dessous:
la source