2009-12-25 13 views
277

Duplicar posibles:
What does map(&:name) mean in Ruby?Rubí signo de colon acceso directo

En Rubí, sé que si lo hago:

some_objects.each(&:foo) 

Es lo mismo que

some_objects.each { |obj| obj.foo } 

Es decir, &:foo crea el bloque { |obj| obj.foo }, lo convierte en un Proc y lo pasa a cada uno. ¿Por qué funciona esto? ¿Es solo un caso especial de Ruby, o hay alguna razón por la cual funciona así?

+0

Esto también se conoce como [pretzel] (http://blog.honeybadger.io/how-ruby-ampersand-colon-works/) [colon] (http://technology.customink.com/blog/ 2015/06/08/ruby-pretzels /) sintaxis. – anothermh

Respuesta

430

Lo que está sucediendo aquí no es "ampersand and colon", es "ampersand and object". El colon en este caso es para el símbolo. Entonces, hay & y hay :foo.

El & llama al y lo pasa como un bloque al método. En Rails, to_proc se implementa en Symbol, por lo que estas dos llamadas son equivalentes:

something {|i| i.foo } 
something(&:foo) 

Además, to_proc en Symbol se implementa en Ruby 1.8.7 y 1.9, por lo que es, de hecho, una "cosa rubí".

Por lo tanto, para resumir: & llama to_proc en el objeto y lo pasa como un bloque con el método, y Ruby implementa to_proc en Symbol.

+71

Más precisamente: el ampersand descomprime el objeto 'Proc' para que se pase como si fuera un bloque literal. Solo si el objeto no es * ya * un objeto 'Proc', ¿llama' to_proc'. –

+0

Símbolo # to_proc solo es nativo en Ruby> 1.9 –

+6

@Steve: No, también está en 1.8.7. p RUBY_VERSION # => "1.8.7" p [ "a", "b", "c"] mapa (Y: upcase). # => [ "A", "B", "C "] –

69

No hay nada de especial en la combinación del ampersand y el símbolo. Aquí hay un ejemplo que (ab) usa la expresión regular:

class Regexp 
    def to_proc 
    ->(str) { self =~ str ; $1 } 
    end 
end 
%w(station nation information).map &/(.*)ion/ 

=> ["stat", "nat", "informat"] 

O enteros.

class Integer 
    def to_proc 
    ->(arr) { arr[self] } 
    end 
end 

arr = [[*3..7],[*14..27],[*?a..?z]] 
arr.map &4 
=> [7, 18, "e"] 

Quién necesita arr.map(&:fifth) cuando se tiene arr.map &4?

+3

Me gustó este ejemplo mejor que la respuesta marcada como correcta – Donato

Cuestiones relacionadas