2011-11-17 6 views
50

Sto provando a definire un blocco che utilizzerò per passare ogni metodo di più intervalli. Invece di ridefinire il blocco su ogni gamma, mi piacerebbe creare un Lamba, e passare il lambda in quanto tale:Passaggio di una lambda come blocco

count = 0 
procedure = lambda {|v| map[count+=1]=v} 
("A".."K").each procedure 
("M".."N").each procedure 
("P".."Z").each procedure 

Tuttavia, ottengo il seguente errore:

 
ArgumentError: wrong number of arguments(1 for 0) 
    from code.rb:23:in `each' 

Tutte le idee che di sta succedendo qui?

risposta

65

Tack una e commerciale (&) sul l'argomento, ad esempio:

("A".."K").each &procedure 

Questo significa che si sta passando come parametro di blocco speciale del metodo. Altrimenti è interpretato come un argomento normale.

Rispecchia anche loro modo che ci catturano e accedere al parametro di blocco all'interno del metodo stesso:

# the & here signifies that the special block parameter should be captured 
# into the variable `procedure` 
def some_func(foo, bar, &procedure) 
    procedure.call(foo, bar) 
end 

some_func(2, 3) {|a, b| a * b } 
=> 6 
12

Il trucco sta utilizzando un & che racconta Ruby per convertire questo argomento per un Proc se necessario e quindi utilizzare l'oggetto come blocco del metodo. A partire da Ruby 1.9 c'è una scorciatoia per le funzioni lambda (anonime). Quindi, è possibile scrivere codice come questo:

(1..5).map &->(x){ x*x } 
# => [1, 4, 9, 16, 25] 

prenderà ogni elemento dell'array e calcolare il suo potere

è lo stesso di questo codice:

func = ->(x) { x*x } 
(1..5).map &func 

per Ruby 1.8:

(1..5).map &lambda {|x| x*x} 
# => [1, 4, 9, 16, 25] 

Per risolvere il problema è possibile utilizzare il metodo di Array reduce (0 è valore iniziale):

('A'..'K').reduce(0) { |sum,elem| sum + elem.size } 
# => 11 

Passando una funzione lambda per reduce è un po 'complicato, ma il blocco anonimo è più o meno lo stesso di lambda.

('A'..'K').reduce(0) { |sum, elem| ->(sum){ sum + 1}.call(sum) } 
# => 11 

Oppure si potrebbe concat lettere proprio come questo:

('A'..'K').reduce(:+) 
=> "ABCDEFGHIJK" 

Converti in minuscole:

('A'..'K').map &->(a){ a.downcase } 
=> ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k"] 

Nel contesto di una definizione di metodo, mettendo una e commerciale di fronte l'ultima parametro indica che un metodo può prendere un blocco e ci dà un nome per riferirsi a questo blocco all'interno del corpo del metodo.

Problemi correlati