ruby - ejemplos - Pasando un lambda como un bloque
django (2)
Estoy tratando de definir un bloque que usaré para pasar cada método de rangos múltiples. En lugar de redefinir el bloque en cada rango, me gustaría crear un lamba y pasar el lambda como tal:
count = 0
procedure = lambda {|v| map[count+=1]=v}
("A".."K").each procedure
("M".."N").each procedure
("P".."Z").each procedure
Sin embargo, me sale el siguiente error:
ArgumentError: wrong number of arguments(1 for 0) from code.rb:23:in `each''
¿Alguna idea de lo que está pasando aquí?
Coloque un ampersand ( &
) en el argumento, por ejemplo:
("A".."K").each &procedure
Esto significa que lo está pasando como el parámetro de bloque especial del método. De lo contrario, se interpreta como un argumento normal.
También refleja la forma en que capturaría y accedería al parámetro de bloque dentro del método mismo:
# 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
El truco está en usar un &
que le dice a Ruby que convierta este argumento a un Proc
si es necesario y luego usar el objeto como el bloque del método. A partir de Ruby 1.9 hay un atajo para funciones lambda (anónimas). Entonces, puedes escribir código como este:
(1..5).map &->(x){ x*x }
# => [1, 4, 9, 16, 25]
tomará cada elemento de la matriz y calculará su poder
es lo mismo que este código:
func = ->(x) { x*x }
(1..5).map &func
para Ruby 1.8:
(1..5).map &lambda {|x| x*x}
# => [1, 4, 9, 16, 25]
Para resolver su problema, puede usar el método de Array reduce
( 0
es el valor inicial):
(''A''..''K'').reduce(0) { |sum,elem| sum + elem.size }
# => 11
Pasar una función lambda para reduce
es un poco complicado, pero el bloque anónimo es más o menos lo mismo que lambda.
(''A''..''K'').reduce(0) { |sum, elem| ->(sum){ sum + 1}.call(sum) }
# => 11
O podrías escribir letras como esta:
(''A''..''K'').reduce(:+)
=> "ABCDEFGHIJK"
Convertir a minúsculas:
(''A''..''K'').map &->(a){ a.downcase }
=> ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k"]
En el contexto de una definición de método, poner un signo & delante del último parámetro indica que un método puede tomar un bloque y nos da un nombre para referirnos a este bloque dentro del cuerpo del método.