2009-12-25 15 views
277

Eventuali duplicati:
What does map(&:name) mean in Ruby?Rubino e commerciale del colon scorciatoia

In Ruby, so che se faccio:

some_objects.each(&:foo) 

E 'lo stesso di

some_objects.each { |obj| obj.foo } 

Cioè, &:foo crea il blocco { |obj| obj.foo }, lo trasforma in un Proc e lo passa a ciascuno. Perché funziona? È solo un caso speciale Ruby, o c'è una ragione per cui funziona così?

+0

Questo viene anche definito [pretzel] (http://blog.honeybadger.io/how-ruby-ampersand-colon-works/) [due punti] (http://technology.customink.com/blog/ 2015/06/08/ruby-pretzels /) sintassi. – anothermh

risposta

430

Quello che sta succedendo qui non è "e commerciale e colon", è "e commerciale e oggetto". Il colon in questo caso è per il simbolo. Quindi, c'è & e c'è lo :foo.

& chiama to_proc sull'oggetto e lo passa come blocco al metodo. In Rails, to_proc è implementato su Symbol, in modo che queste due chiamate sono equivalenti:

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

Inoltre, to_proc su Symbol è implementato in Ruby 1.8.7 e 1.9, quindi è in realtà una "cosa ruby".

Quindi, per riassumere: & chiama to_proc sull'oggetto e lo passa come un blocco al metodo, e Ruby implementa to_proc su Symbol.

+71

Più precisamente: la e commerciale spacchetta l'oggetto 'Proc' in modo che venga passato come se fosse un blocco letterale. Solo se l'oggetto non è * già * un oggetto 'Proc', chiama' to_proc'. –

+0

Il simbolo # to_proc è nativo solo in Ruby> 1.9 –

+6

@Steve: No, è anche in 1.8.7. p RUBY_VERSION # => "1.8.7" p ["a", "b", "c"]. Map (&: upcase) # => ["A", "B", "C "] –

69

Non c'è niente di speciale nella combinazione della e commerciale e del simbolo. Ecco un esempio che (ab) utilizza la regex:

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

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

Oppure numeri interi.

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

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

Chi ha bisogno arr.map(&:fifth) quando si hanno arr.map &4?

+3

È piaciuto questo esempio meglio della risposta corretta – Donato