web-dev-qa-db-fra.com

Comment passer une fonction au lieu d'un bloc

Duplicata possible:
Manière plus courte de passer chaque élément d'un tableau à une fonction

Je sais que cela fonctionnera:

def inc(a)
  a+1
end
[1,2,3].map{|a| inc a}

mais en Python, j'ai juste besoin d'écrire:

map(inc, [1,2,3])

ou

[inc(x) for x in [1,2,3])

Je me demandais si je pouvais ignorer les étapes de création d'un bloc dans Ruby, et j'ai fait ceci:

[1,2,3].map inc
# => ArgumentError: wrong number of arguments (0 for 1)
# from (irb):19:in `inc'

Quelqu'un at-il des idées sur la façon de procéder?

48
Hanfei Sun

Selon " Passer des méthodes comme des blocs dans Ruby ", vous pouvez passer une méthode comme un bloc comme ceci:

p [1,2,3].map(&method(:inc))

Je ne sais pas si c'est beaucoup mieux que de rouler votre propre bloc, honnêtement.

Si votre méthode est définie sur la classe des objets que vous utilisez, vous pouvez le faire:

# Adding inc to the Integer class in order to relate to the original post.
class Integer
  def inc
    self + 1
  end
end

p [1,2,3].map(&:inc)

Dans ce cas, Ruby interprétera le symbole comme un nom de méthode d'instance et tentera d'appeler la méthode sur cet objet.


La raison pour laquelle vous pouvez passer un nom de fonction en tant qu'objet de première classe en Python, mais pas en Ruby, est que Ruby vous permet d'appeler une méthode avec zéro argument sans parenthèses. La grammaire de Python, depuis il requiert les parenthèses, empêche toute ambiguïté possible entre la transmission d'un nom de fonction et l'appel d'une fonction sans arguments.

75
Platinum Azure

Ne répond pas à votre question mais si vous voulez vraiment incrémenter toutes vos variables, vous avez Integer#next

4.next
#=> 5

[1,2,3].map(&:next)
#=> [2, 3, 4]
9
oldergod