Encontrei esse código em um RailsCast :
def tag_names
@tag_names || tags.map(&:name).join(' ')
end
O que significa (&:name)
in map(&:name)
?
ruby
syntax
operators
parameter-passing
collimarco
fonte
fonte
Respostas:
É uma abreviação de
tags.map(&:name.to_proc).join(' ')
Se
foo
é um objeto com umto_proc
método, você pode passá-lo para um método como&foo
, que o chamaráfoo.to_proc
e usará como bloco do método.O
Symbol#to_proc
método foi originalmente adicionado pelo ActiveSupport, mas foi integrado ao Ruby 1.8.7. Esta é a sua implementação:fonte
&
, ou sejatags.map(&:name.to_proc).join(' ')
Outra abreviação legal, desconhecida para muitos, é
que é uma abreviação de
Ao chamar
method(:foo)
, pegamos umMethod
objetoself
que representa seufoo
método e usamos o&
para significar que ele possui umto_proc
método que o converte em aProc
.Isso é muito útil quando você deseja fazer coisas sem estilo. Um exemplo é verificar se há alguma string em uma matriz igual à string
"foo"
. Existe a maneira convencional:E existe o caminho sem pontos:
A maneira preferida deve ser a mais legível.
fonte
array.each{|e| foo(e)}
é mais curto ainda :-) +1 de qualquer maneira&method
?[1,2,3].map(&Array.method(:new))
É equivalente a
fonte
Embora também observemos que a
#to_proc
magia e comercial pode funcionar com qualquer classe, não apenas com o Symbol. Muitos Rubyists optam por definir#to_proc
na classe Array:E comercial
&
funciona enviandoto_proc
mensagem em seu operando, que, no código acima, é da classe Array. E desde que eu defini o#to_proc
método na matriz, a linha se torna:fonte
É uma abreviação de
tags.map { |tag| tag.name }.join(' ')
fonte
&
operador unário chamato_proc
seu operando. Portanto, não é específico para o método de mapa e, de fato, funciona em qualquer método que pega um bloco e passa um ou mais argumentos para o bloco.é o mesmo que
&:name
apenas usa o símbolo como o nome do método a ser chamado.fonte
A resposta de Josh Lee está quase correta, exceto que o código Ruby equivalente deveria ter sido o seguinte.
não
Com esse código, quando
print [[1,'a'],[2,'b'],[3,'c']].map(&:first)
é executado, Ruby divide a primeira entrada[1,'a']
em 1 e 'a' para fornecerobj
1 eargs*
'a' para causar um erro, pois o objeto Fixnum 1 não possui o método self (que é: first).Quando
[[1,'a'],[2,'b'],[3,'c']].map(&:first)
é executado;:first
é um objeto Symbol, portanto, quando&:first
é fornecido um método de mapa como parâmetro, o símbolo # to_proc é chamado.O mapa envia uma mensagem de chamada para: first.to_proc com o parâmetro
[1,'a']
, por exemplo,:first.to_proc.call([1,'a'])
é executado.O procedimento to_proc na classe Symbol envia uma mensagem de envio para um objeto de matriz (
[1,'a']
) com o parâmetro (: first), por exemplo,[1,'a'].send(:first)
é executado.itera sobre o restante dos elementos no
[[1,'a'],[2,'b'],[3,'c']]
objeto.É o mesmo que executar
[[1,'a'],[2,'b'],[3,'c']].map(|e| e.first)
expressão.fonte
[1,2,3,4,5,6].inject(&:+)
- injetar espera um lambda com dois parâmetros (MEMO e item) e:+.to_proc
entrega-lo -Proc.new |obj, *args| { obj.send(self, *args) }
ou{ |m, o| m.+(o) }
Duas coisas estão acontecendo aqui, e é importante entender as duas coisas.
Conforme descrito em outras respostas, o
Symbol#to_proc
método está sendo chamado.Mas o motivo pelo qual
to_proc
o símbolo está sendo chamado é porque ele está sendo passadomap
como um argumento de bloco. Colocar&
na frente de um argumento em uma chamada de método faz com que seja passado dessa maneira. Isso é verdade para qualquer método Ruby, não apenasmap
com símbolos.O
Symbol
é convertido em umProc
porque é passado como um bloco. Podemos mostrar isso tentando passar um proc.map
sem o e comercial:Mesmo que não precise ser convertido, o método não saberá como usá-lo, pois espera um argumento de bloco. Passá-lo
&
fornece.map
o bloco que ele espera.fonte
(&: name) é a abreviação de (&: name.to_proc) e é o mesmo que
tags.map{ |t| t.name }.join(' ')
to_proc é realmente implementado em C
fonte
map (&: name) pega um objeto enumerável (tags no seu caso) e executa o método name para cada elemento / tag, produzindo cada valor retornado pelo método.
É uma abreviação de
que retorna a matriz de nomes de elementos (tags)
fonte
Basicamente, executa a chamada de método
tag.name
em cada tag na matriz.É uma abreviação simplificada de rubi.
fonte
Embora já tenhamos ótimas respostas, procurando uma perspectiva de iniciante, gostaria de adicionar as informações adicionais:
Isso significa que você está passando outro método como parâmetro para a função de mapa. (Na realidade, você está passando um símbolo que é convertido em um processo. Mas isso não é tão importante nesse caso específico).
O importante é que você tenha um
method
nomename
que será usado pelo método do mapa como argumento em vez doblock
estilo tradicional .fonte
Primeiro,
&:name
é um atalho para&:name.to_proc
, onde:name.to_proc
retorna aProc
(algo semelhante, mas não idêntico a um lambda) que, quando chamado com um objeto como argumento (primeiro), chama oname
método nesse objeto.Segundo, enquanto
&
indef foo(&block) ... end
converte um bloco passado parafoo
aProc
, ele faz o oposto quando aplicado a aProc
.Assim,
&:name.to_proc
é um bloco que pega um objeto como argumento e chama oname
método nele, ie{ |o| o.name }
.fonte
Aqui
:name
está o símbolo que aponta para o métodoname
do objeto tag. Quando passamos&:name
paramap
, ele será tratadoname
como um objeto proc. Para resumir,tags.map(&:name)
atua como:fonte
Isso significa
fonte
É o mesmo que abaixo:
fonte