Encontré este código en un RailsCast :
def tag_names
@tag_names || tags.map(&:name).join(' ')
end
¿Qué significa el (&:name)
en map(&:name)
?
ruby
syntax
operators
parameter-passing
collimarco
fuente
fuente
Respuestas:
Es taquigrafía para
tags.map(&:name.to_proc).join(' ')
Si
foo
es un objeto con unto_proc
método, puede pasarlo a un método como&foo
, que lo llamaráfoo.to_proc
y lo usará como bloque del método.El
Symbol#to_proc
método fue agregado originalmente por ActiveSupport pero se ha integrado en Ruby 1.8.7. Esta es su implementación:fuente
&
, es decirtags.map(&:name.to_proc).join(' ')
Otra taquigrafía genial, desconocida para muchos, es
que es una abreviatura de
Al llamar
method(:foo)
, tomamos unMethod
objetoself
que representa sufoo
método, y lo usamos&
para indicar que tiene unto_proc
método que lo convierte en aProc
.Esto es muy útil cuando quieres hacer cosas sin estilo. Un ejemplo es verificar si hay alguna cadena en una matriz que sea igual a la cadena
"foo"
. Existe la forma convencional:Y existe la forma sin puntos:
La forma preferida debería ser la más legible.
fuente
array.each{|e| foo(e)}
es aún más corto :-) +1 de todos modos&method
?[1,2,3].map(&Array.method(:new))
Es equivalente a
fuente
Si bien también tengamos en cuenta que el ampersand
#to_proc
magic puede funcionar con cualquier clase, no solo Symbol. Muchos rubíes eligen definir#to_proc
en la clase de matriz:Ampersand
&
funciona enviando unto_proc
mensaje en su operando, que, en el código anterior, es de la clase Array. Y desde que definí el#to_proc
método en Array, la línea se convierte en:fuente
Es taquigrafía para
tags.map { |tag| tag.name }.join(' ')
fuente
&
operador unario llamato_proc
a su operando. Por lo tanto, no es específico del método de mapa, y de hecho funciona en cualquier método que tome un bloque y pase uno o más argumentos al bloque.es lo mismo que
&:name
solo usa el símbolo como el nombre del método a llamar.fuente
La respuesta de Josh Lee es casi correcta, excepto que el código Ruby equivalente debería haber sido el siguiente.
no
Con este código, cuando
print [[1,'a'],[2,'b'],[3,'c']].map(&:first)
se ejecuta, Ruby divide la primera entrada[1,'a']
en 1 y 'a' para darobj
1 yargs*
'a' para causar un error ya que el objeto Fixnum 1 no tiene el método self (que es: primero).Cuando
[[1,'a'],[2,'b'],[3,'c']].map(&:first)
se ejecuta;:first
es un objeto Symbol, por lo que cuando&:first
se le da un método de mapa como parámetro, se invoca Symbol # to_proc.map envía un mensaje de llamada a: first.to_proc con el parámetro
[1,'a']
, por ejemplo,:first.to_proc.call([1,'a'])
se ejecuta.El procedimiento to_proc en la clase Symbol envía un mensaje de envío a un objeto de matriz (
[1,'a']
) con el parámetro (: primero), por ejemplo,[1,'a'].send(:first)
se ejecuta.itera sobre el resto de los elementos en el
[[1,'a'],[2,'b'],[3,'c']]
objeto.Esto es lo mismo que ejecutar
[[1,'a'],[2,'b'],[3,'c']].map(|e| e.first)
expresión.fuente
[1,2,3,4,5,6].inject(&:+)
- Inyectar espera una lambda con dos parámetros (MEMO) y el tema y:+.to_proc
lo entrega -Proc.new |obj, *args| { obj.send(self, *args) }
o{ |m, o| m.+(o) }
Aquí están sucediendo dos cosas, y es importante comprender ambas.
Como se describe en otras respuestas, el
Symbol#to_proc
se llama método.Pero la razón por la que
to_proc
se llama al símbolo es porque se pasamap
como un argumento de bloque. Colocar&
delante de un argumento en una llamada a un método hace que se pase de esta manera. Esto es cierto para cualquier método de Ruby, no solomap
con símbolos.El
Symbol
se convierte en aProc
porque se pasa como un bloque. Podemos mostrar esto tratando de pasar un proceso.map
sin el signo y:Aunque no es necesario convertirlo, el método no sabrá cómo usarlo porque espera un argumento de bloque. Pasarlo con
&
da.map
el bloqueo que espera.fuente
(&: name) es la abreviatura de (&: name.to_proc) es igual que
tags.map{ |t| t.name }.join(' ')
to_proc se implementa realmente en C
fuente
mapa (&: nombre) toma un objeto enumerable (etiquetas en su caso) y ejecuta el método de nombre para cada elemento / etiqueta, generando cada valor devuelto por el método.
Es una abreviatura de
que devuelve la matriz de nombres de elementos (etiquetas)
fuente
Básicamente ejecuta la llamada al método
tag.name
en cada etiqueta de la matriz.Es una taquigrafía rubí simplificada.
fuente
Aunque ya tenemos excelentes respuestas, mirando desde la perspectiva de un principiante me gustaría agregar la información adicional:
Esto significa que está pasando otro método como parámetro a la función de mapa. (En realidad, está pasando un símbolo que se convierte en un proceso. Pero esto no es tan importante en este caso particular).
Lo importante es que tenga un
method
nombrename
que será utilizado por el método de mapa como argumento en lugar delblock
estilo tradicional .fuente
Primero,
&:name
es un atajo para&:name.to_proc
, donde:name.to_proc
devuelve unProc
(algo que es similar, pero no idéntico a un lambda) que cuando se llama con un objeto como (primer) argumento, llama alname
método en ese objeto.En segundo lugar, mientras que
&
endef foo(&block) ... end
conversiones un bloque pasa afoo
aProc
, hace lo contrario cuando se aplica a aProc
.Por lo tanto,
&:name.to_proc
es un bloque que toma un objeto como argumento y llama alname
método sobre él, es decir{ |o| o.name }
.fuente
Aquí
:name
está el símbolo que apunta al métodoname
de etiqueta de objeto. Cuando pasamos&:name
amap
, se trataráname
como un objeto proc. Para abreviar,tags.map(&:name)
actúa como:fuente
significa
fuente
Es lo mismo a continuación:
fuente