2012-03-29 14 views
39

Dato il seguente array a:Come passare un argomento a shortcut array.map?

a = [1, 2, 3, 4, 5] 

Come posso fare:

a.map { |num| num + 1 } 

utilizzando la notazione abbreviata:

a.map(&:+ 1) 

o:

a.map(&:+ 2) 

dove 1 e 2 sono gli argomenti?

+16

Cheating: '[1, 2, 3, 4, 5] .map (&: next) # => [2, 3, 4, 5, 6]' –

+0

Potresti essere interessato a [Enumeratori] di Ruby (http://www.ruby-doc.org/core-2.1.2/Enumerator.html). – alxndr

risposta

33

Non puoi farlo in questo modo. L'operatore & serve per trasformare i simboli in procs.

a = [1, 2, 3, 4, 5] 
puts a.map(&:to_s) # prints array of strings 
puts a.map(&:to_s2) # error, no such method `to_s2`. 

& è una scorciatoia per to_proc:

def to_proc 
    proc { |obj, *args| obj.send(self, *args) } 
end 

Crea e restituisce nuova proc. Come vedi, non puoi passare alcun parametro a questo metodo. Puoi solo chiamare il proc generato.

+0

hai ragione: dal momento che array.map (&: some_method) è l'abbreviazione di: class Symbol def to_proc proc {| obj, * args | obj.send (self, * args)} fine fine. come passi in * arg? –

+0

@not_nil: non lo fai. Usa il normale blocco/proc. –

+2

@not_nil: Ruby non supporta lo stile point-free per tutto ciò che va oltre "Symbol # to_proc', perché manca di composizione delle funzioni e currying. Vieni da uno sfondo funzionale? –

24

Non è possibile farlo con map. Ma guardate Facets 'Enumerable#map_send:

require 'facets' 
[1, 2, 3].map_send(:+, 1) 
#=> [2, 3, 4] 

Scrivere la propria implementazione è piuttosto semplice:

module Enumerable 
    def map_send(*args) 
    map { |obj| obj.send(*args) } 
    end 
end 
0

Se è davvero necessario è possibile utilizzare la libreria Ampex, ma non so se è ancora gestita.

Problemi correlati