68 votes

Passer un lambda en bloc

J'essaie de définir un bloc que je vais utiliser pour passer le chaque méthode de plusieurs plages. Plutôt que de redéfinir le bloc sur chaque plage, j'aimerais créer un lamba et transmettre le lambda en tant que tel:

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

Cependant, j'obtiens l'erreur suivante:

ArgumentError: nombre d'arguments incorrect (1 pour 0)
    de code.rb: 23: dans «each»

Des idées ce qui se passe ici?

87voto

numbers1311407 Points 15653

Pointez un et commercial ( & ) sur l'argument, par exemple:

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

Cela signifie que vous le transmettez en tant que paramètre de bloc spécial de la méthode. Sinon, il est interprété comme un argument normal.

Cela reflète également leur manière de capturer et d'accéder au paramètre de bloc dans la méthode elle-même:

 # 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
 

25voto

Tombart Points 4503

Le truc, c'est à l'aide d'un & qui dit Ruby pour convertir cet argument à un Proc , si nécessaire, et ensuite utiliser l'objet comme la méthode du bloc. À partir de Ruby 1.9 il y a un raccourci pour lambda (anonyme) de fonctions. Donc, vous pouvez écrire du code comme ceci:

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

aura lieu à chaque élément du tableau et calculer sa puissance

c'est le même que ce code:

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

pour Ruby 1.8:

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

Pour résoudre votre problème, vous pouvez utiliser le Tableau de la méthode de reduce (0 est la valeur initiale):

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

Passage d'une fonction lambda d' reduce est un peu délicat, mais le bloc anonyme est à peu près le même que lambda.

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

Ou vous pourriez concat lettres comme cela:

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

Convertir en minuscules:

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

Dans le contexte d'une définition de la méthode, de mettre une esperluette devant le dernier paramètre indique qu'une méthode peut prendre un bloc et nous donne un nom pour désigner ce bloc dans le corps de la méthode.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X